1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.cxx,v $
5 Date: $Date: 2009/05/28 14:22:09 $
6 Version: $Revision: 1.47 $
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 bbmInitialized(false),
113 bbmBoxProcessMode("Pipeline"),
117 bbtkBlackBoxDebugMessage("object",4,"==> BlackBox::BlackBox(\""
118 <<name<<"\")"<<std::endl);
119 bbtkBlackBoxDebugMessage("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 bbmInitialized(false),
135 bbmBoxProcessMode(from.bbmBoxProcessMode),
139 bbtkBlackBoxDebugMessage("object",4,"==> BlackBox::BlackBox("
140 <<from.bbGetFullName()<<",\""
141 <<name<<"\")"<<std::endl);
142 bbtkBlackBoxDebugMessage("object",4,"<== BlackBox::BlackBox("
143 <<from.bbGetFullName()<<",\""
144 <<name<<"\")"<<std::endl);
146 //=========================================================================
149 //=========================================================================
150 BlackBox::~BlackBox()
152 bbtkBlackBoxDebugMessage("object",4,"==> BlackBox::~BlackBox() ["<<bbmName
154 this->bbDesallocateConnectors();
155 bbtkBlackBoxDebugMessage("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 bbtkBlackBoxDebugMessage("kernel",8,
200 "BlackBox::bbHasInput(\""
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 bbtkBlackBoxDebugMessage("kernel",8,"BlackBox::bbHasOutput(\""
218 bool r = ( bbGetDescriptor()->GetOutputDescriptorMap().find(name)
219 != bbGetDescriptor()->GetOutputDescriptorMap().end());
220 bbtkDebugDecTab("kernel",8);
223 //=========================================================================
226 //=========================================================================
227 /// Gets the output type of a given name
228 TypeInfo BlackBox::bbGetOutputType( const std::string &name ) const
230 bbtkBlackBoxDebugMessage("kernel",8,
231 "BlackBox::bbGetOutputType(\""
234 TypeInfo r = bbGetDescriptor()->GetOutputDescriptor(name)->GetTypeInfo();
235 bbtkDebugDecTab("kernel",8);
238 //=========================================================================
240 //=========================================================================
241 /// Gets the input type of a given name
242 TypeInfo BlackBox::bbGetInputType( const std::string &name ) const
244 bbtkBlackBoxDebugMessage("kernel",8,
245 "BlackBox::bbGetInputType(\""
248 TypeInfo r = bbGetDescriptor()->GetInputDescriptor(name)->GetTypeInfo();
249 bbtkDebugDecTab("kernel",8);
252 //=========================================================================
255 //=========================================================================
256 /// Allocates the i/o connectors of the black box
257 void BlackBox::bbAllocateConnectors()
259 bbtkBlackBoxDebugMessage("kernel",8,
260 "BlackBox::bbAllocateConnectors()"
263 MakeBlackBoxPointer(this,true);
265 const BlackBoxDescriptor::InputDescriptorMapType& imap
266 = bbGetDescriptor()->GetInputDescriptorMap();
267 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
268 for ( i = imap.begin(); i != imap.end(); ++i )
270 bbtkBlackBoxDebugMessage("kernel",8,"* Allocate \""<<i->first<<"\""<<std::endl);
271 bbGetInputConnectorMap()[i->second->GetName()]
272 = new BlackBoxInputConnector(GetThisPointer<BlackBox>());
274 const BlackBoxDescriptor::OutputDescriptorMapType& omap
275 = bbGetDescriptor()->GetOutputDescriptorMap();
276 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
277 for ( o = omap.begin(); o != omap.end(); ++o )
279 bbtkBlackBoxDebugMessage("kernel",8,"* Allocate \""<<o->first<<"\""<<std::endl);
280 bbGetOutputConnectorMap()[o->second->GetName()]
281 = new BlackBoxOutputConnector(GetThisPointer<BlackBox>());
285 //=========================================================================
288 //=========================================================================
289 /// Desallocates the i/o connectors of the black box
290 void BlackBox::bbDesallocateConnectors()
292 bbtkBlackBoxDebugMessage("kernel",8,
293 "BlackBox::bbDesallocateConnectors()"
296 InputConnectorMapType::const_iterator i;
297 for ( i = bbGetInputConnectorMap().begin();
298 i != bbGetInputConnectorMap().end(); ++i )
300 bbtkBlackBoxDebugMessage("kernel",8,"* Delete \""<<i->first<<"\""<<std::endl);
303 OutputConnectorMapType::const_iterator o;
304 for ( o = bbGetOutputConnectorMap().begin();
305 o != bbGetOutputConnectorMap().end(); ++o )
307 bbtkBlackBoxDebugMessage("kernel",8,"* Delete \""<<o->first<<"\""<<std::endl);
311 bbtkDebugDecTab("kernel",8);
314 //=========================================================================
317 //=========================================================================
318 /// Copies the input / output values from another box
319 void BlackBox::bbCopyIOValues(BlackBox& from)
321 bbtkBlackBoxDebugMessage("kernel",1,
322 "BlackBox::bbCopyIOValues("
323 <<from.bbGetFullName()<<")"
325 // copies the input values
326 const BlackBoxDescriptor::InputDescriptorMapType& imap
327 = bbGetDescriptor()->GetInputDescriptorMap();
328 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
329 for ( i = imap.begin(); i != imap.end(); ++i )
331 if (! i->second->GetCopyConstruct() ) continue;
332 std::string input = i->second->GetName();
333 bbtkBlackBoxDebugMessage("kernel",2,"* Copying input "<<input<<std::endl);
334 this->bbSetInput(input, from.bbGetInput(input) );
336 // copies the output values
337 const BlackBoxDescriptor::OutputDescriptorMapType& omap
338 = bbGetDescriptor()->GetOutputDescriptorMap();
339 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
340 for ( o = omap.begin(); o != omap.end(); ++o )
342 if (! o->second->GetCopyConstruct() ) continue;
343 std::string output = o->second->GetName();
344 bbtkBlackBoxDebugMessage("kernel",2,"* Copying output "<<output<<std::endl);
345 this->bbSetOutput(output, from.bbGetOutput(output) );
348 bbtkDebugDecTab("kernel",9);
351 //=========================================================================
355 //=========================================================================
356 bool BlackBox::bbCanReact() const
358 return ( bbGlobalGetSomeBoxExecuting()
360 || Wx::IsSomeWindowAlive()
364 //=========================================================================
368 //=========================================================================
369 /// User overloadable destruction method of a black box
370 void BlackBox::bbUserDelete()
372 bbtkBlackBoxDebugMessage("process",5,
373 "=> BlackBox::bbUserDelete()"
374 <<" : not overloaded; using standard deletion"
378 //=========================================================================
381 //=========================================================================
382 BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const
384 const std::string& p = bbmBoxProcessMode;
386 (p == "P") || (p == "p") ||
387 (p == "Pipeline") || (p == "pipeline") ) return Pipeline;
389 (p == "A") || (p == "a") ||
390 (p == "Always") || (p == "always") ) return Always;
392 (p == "R") || (p == "r") ||
393 (p == "Reactive") || (p == "reactive") ) return Reactive;
396 (p == "F") || (p == "f") ||
397 (p == "Flash") || (p == "flash") ) return Flash;
399 bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
400 <<"' unknown. Possible values : "
401 <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
402 <<"'1'/'A'/'a'/'Always'/'always' | "
403 <<"'2'/'R'/'r'/'Reactive'/'reactive'"
404 // <<"'3'/'F'/'f'/'Flash'/'flash'"
407 //=========================================================================
409 //=========================================================================
410 bool BlackBox::bbBoxProcessModeIsReactive() const
412 return (bbGetBoxProcessModeValue() == Reactive);
414 //=========================================================================
416 //=========================================================================
417 bool BlackBox::bbBoxProcessModeIsAlways() const
419 return (bbGetBoxProcessModeValue() == Always);
421 //=========================================================================
426 //=========================================================================
427 void BlackBox::bbAddOutputObserver(const std::string& output,
428 OutputChangeCallbackType f)
430 bbGetOutputConnector(output).AddChangeObserver(f);
432 //=========================================================================
434 //=========================================================================
435 void BlackBox::bbRemoveOutputObserver(const std::string& output_name,
436 OutputChangeCallbackType f)
438 bbtkError("BlackBox::RemoveChangeObserver NOT IMPLEMENTED");
440 //=========================================================================
444 //=========================================================================
445 /// Sets the ChangeTime of input
446 void BlackBox::bbSetInputChangeTime(BlackBoxInputConnector* c,
449 bbtkBlackBoxDebugMessage("change",1,
450 "==> BlackBox::bbSetInputChangeTime("<<c<<","<<t<<") ["
451 <<bbGetFullName()<<"]"<<std::endl);
453 // If new time is greater than old one
454 if ( c->SetChangeTime(t) )
456 bool was_up_to_date = bbIsUpToDate();
457 // If new time is greater than the old max time of inputs
458 if ( mMaxInputChangeTime.Set(t) )
460 // If the box turned out-of-date
461 if ( was_up_to_date && bbIsOutOfDate() )
464 if ( ( bbBoxProcessModeIsReactive() ||
465 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
468 bbtkBlackBoxDebugMessage("change",2,
471 <<" changed and box is in Reactive mode or BoxExecute input changed : adding it to the global execution list"
473 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
475 // Have to propagate the modification to aval boxes
476 OutputConnectorMapType::iterator i;
477 for (i = bbGetOutputConnectorMap().begin();
478 i != bbGetOutputConnectorMap().end();
481 i->second->SetChangeTime(t);
483 // update the MinOutputChangeTime
484 mMinOutputChangeTime.Set(t);
489 //=========================================================================
491 //=========================================================================
492 /// Sets the ChangeTime of output
493 void BlackBox::bbSetOutputChangeTime(BlackBoxOutputConnector* c,
496 bbtkBlackBoxDebugMessage("change",1,
497 "==> BlackBox::bbSetOutputChangeTime("<<c<<","<<t<<") ["
498 <<bbGetFullName()<<"]"<<std::endl);
502 // c->GetChangeTime() = t;
503 // bbUpdateMinOutputChangeTime(t);
507 //=========================================================================
511 //=========================================================================
512 void BlackBox::bbUpdateMaxInputChangeTime(const ChangeTime& t)
516 if ( t > mMaxInputChangeTime )
518 mMaxInputChangeTime = t;
519 if ( mMinOutputChangeTime > mMaxInputChangeTime )
526 //=========================================================================
528 //=========================================================================
529 void bbUpdateMinOutputChangeTime(const ChangeTime& t)
531 ChangeTime old = mMinOutputChangeTime;
532 mMinOutputChangeTime = MAXLONG;
533 OutputConnectorMapType::iterator i;
534 for (i = bbGetOutputConnectorMap.begin();
535 i != bbGetOutputConnectorMap.end();
538 if (i->second->GetChangeTime() < mMinOutputChangeTime)
539 mMinOutputChangeTime = i->second->GetChangeTime();
541 if ( mMinOutputChangeTime < old )
546 //=========================================================================
549 //=========================================================================
550 /// Signals that the BlackBox has been modified through
551 /// the input connector c
552 /// and propagates it downward
553 /// ** NOT USER INTENDED **
554 void BlackBox::bbSetStatusAndPropagate(BlackBoxInputConnector* c,
557 bbtkBlackBoxDebugMessage("change",5,
558 "=> BlackBox::bbSetStatusAndPropagate(input,"
559 <<GetIOStatusString(s)<<")"
562 if (s==UPTODATE) bbtkError("bbSetStatusAndPropagate with status UPTODATE!");
567 if (bbGetBoxProcessModeValue() == Flash)
573 OutputConnectorMapType::const_iterator o;
574 for ( o = bbGetOutputConnectorMap().begin();
575 o != bbGetOutputConnectorMap().end(); ++o )
577 if (o->second->GetStatus()==UPTODATE)
579 o->second->SetStatus(OUTOFDATE);
580 o->second->SignalChange(GetThisPointer<BlackBox>(),o->first);
584 if ( ( bbBoxProcessModeIsReactive() ||
585 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
588 bbtkBlackBoxDebugMessage("change",2,
589 "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
590 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
592 bbtkBlackBoxDebugMessage("change",5,
593 "<= BlackBox::bbSetStatusAndPropagate(input)"
596 //=========================================================================
599 //=========================================================================
600 void BlackBox::bbSignalOutputModification(bool reaction)
602 bbtkBlackBoxDebugMessage("change",5,
603 "=> BlackBox::bbSignalOutputModification("
607 OutputConnectorMapType::iterator i;
608 for ( i = bbGetOutputConnectorMap().begin();
609 i != bbGetOutputConnectorMap().end(); ++i)
611 // std::cout << "Stat = "
612 //<<GetIOStatusString(i->second->GetStatus())
614 // LG : CANNOT SIGNAL ONLY WHEN UPTODATE
615 // See bbtkSampleOutputObserver
616 // if (i->second->GetStatus()==UPTODATE)
618 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
622 if (reaction) bbGlobalProcessExecutionList();
624 bbtkBlackBoxDebugMessage("change",5,
625 "<= BlackBox::bbSignalOutputModification()"
629 //=========================================================================
630 //=========================================================================
631 void BlackBox::bbSignalOutputModification(const std::string& output,
634 bbtkBlackBoxDebugMessage("change",5,
635 "=> BlackBox::bbSignalOutputModification("
636 <<output<<","<<reaction<<")"
639 OutputConnectorMapType::iterator i =
640 bbGetOutputConnectorMap().find(output);
643 if ( i == bbGetOutputConnectorMap().end() )
645 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
648 // if (i->second->GetStatus()==UPTODATE)
650 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
651 // Has to notify the output "BoxChange" also
652 if (output != "BoxChange")
654 i = bbGetOutputConnectorMap().find("BoxChange");
655 if ( i != bbGetOutputConnectorMap().end() )
657 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
660 if (reaction) bbGlobalProcessExecutionList();
663 bbtkBlackBoxDebugMessage("change",5,
664 "<= BlackBox::bbSignalOutputModification("
669 //=========================================================================
670 //=========================================================================
671 void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
674 bbtkBlackBoxDebugMessage("change",5,
675 "=> BlackBox::bbSignalOutputModification(vector of outputs)"
677 OutputConnectorMapType::iterator i;
678 std::vector<std::string>::const_iterator o;
679 bool changed = false;
680 for (o=output.begin();o!=output.end();++o)
682 // the output "BoxChange" must be signaled **AFTER** all others
683 if (*o == "BoxChange") continue;
684 // Look for the connector
685 i = bbGetOutputConnectorMap().find(*o);
686 if ( i == bbGetOutputConnectorMap().end() )
688 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
691 // if (i->second->GetStatus()==UPTODATE)
693 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
697 // Has to notify the output "BoxChange" also
698 i = bbGetOutputConnectorMap().find("BoxChange");
699 if ( changed && (i != bbGetOutputConnectorMap().end()))
701 // if (i->second->GetStatus()==UPTODATE)
703 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
704 if (reaction) bbGlobalProcessExecutionList();
708 bbtkBlackBoxDebugMessage("change",5,
709 "<= BlackBox::bbSignalOutputModification(vector of outputs)"
713 //=========================================================================
721 //=========================================================================
722 /// Main processing method of the box.
723 void BlackBox::bbExecute(bool force)
725 bbtkBlackBoxDebugMessage("process",2,
726 "=> BlackBox::bbExecute("<<(int)force<<")"
729 // If already executing : return
731 if (bbGetExecuting())
733 bbtkBlackBoxDebugMessage("process",2,
734 " -> already executing : abort"<<std::endl);
739 // If execution frozen : return
740 if (bbGlobalGetFreezeExecution())
742 bbtkBlackBoxDebugMessage("process",2,
743 " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
748 // If force is true then update is triggered even if the box is UPTODATE
749 // if (force) bbSetModifiedStatus();
751 // Calls the main recursive execution method
752 bbRecursiveExecute(Connection::Pointer());
754 bbtkBlackBoxDebugMessage("process",2,
755 "<= BlackBox::bbExecute()"
758 //=========================================================================
760 //=========================================================================
761 void BlackBox::bbInitializeProcessing()
765 bbtkBlackBoxDebugMessage("process",2,"** Initialize processing"
767 this->bbRecursiveInitializeProcessing();
768 bbmInitialized = true;
771 //=========================================================================
773 //=========================================================================
774 void BlackBox::bbFinalizeProcessing()
778 bbtkBlackBoxDebugMessage("process",2,"** Finalize processing"
780 this->bbRecursiveFinalizeProcessing();
781 bbmInitialized = false;
784 //=========================================================================
787 //=========================================================================
788 /// Main recursive processing method of the box.
789 void BlackBox::bbRecursiveExecute( Connection::Pointer caller )
791 bbtkBlackBoxDebugMessage("process",3,
792 "=> BlackBox::bbRecursiveExecute("
793 <<(caller?caller->GetFullName():"0")<<")"
796 // If already executing : return
797 if (bbGetExecuting())
799 bbtkBlackBoxDebugMessage("process",3,
800 " -> already executing : abort"<<std::endl);
804 // If not initialized do it
805 bbInitializeProcessing();
807 bbSetExecuting(true);
808 bool wasExecuting = bbGlobalGetSomeBoxExecuting();
809 bbGlobalSetSomeBoxExecuting(true);
811 // Creates the window if the black box has one
812 this->bbCreateWindow();
814 // Updates its inputs
815 IOStatus s = bbUpdateInputs();
817 if ( (s != UPTODATE) ||
818 bbBoxProcessModeIsAlways() )
820 // Displays the window (WxBlackbox)
821 // bbShowWindow(caller);
823 // Actual processing (virtual)
827 // Update the I/O statuses
828 bbComputePostProcessStatus();
832 // Test output status...
833 OutputConnectorMapType::iterator o;
834 for ( o = bbGetOutputConnectorMap().begin();
835 o!= bbGetOutputConnectorMap().end(); ++o)
837 if (o->second->GetStatus() != UPTODATE)
839 bbtkWarning("BlackBox::bbRecursiveExecute: "
840 <<"all inputs are Up-to-date but output '"
841 <<o->first<<"' is Out-of-date ???");
845 bbtkBlackBoxDebugMessage("process",3," -> Up-to-date : nothing to do"
849 // Shows the window if the black box has one
850 this->bbShowWindow();
853 bbtkBlackBoxDebugMessage("process",3,
854 "<= BlackBox::bbRecursiveExecute()"
857 bbSetExecuting(false);
858 bbGlobalSetSomeBoxExecuting(wasExecuting);
863 //=========================================================================
869 //=========================================================================
870 /// Updates the BlackBox inputs
871 /// Calls RecursiveExecute on all BlackBoxInputConnector
872 /// \returns The maximum of final IOStatus after each input update
873 IOStatus BlackBox::bbUpdateInputs()
875 bbtkBlackBoxDebugMessage("process",4,
876 "=> BlackBox::bbUpdateInputs()"
879 IOStatus s = UPTODATE;
881 InputConnectorMapType::iterator i;
882 for ( i = bbGetInputConnectorMap().begin();
883 i!= bbGetInputConnectorMap().end(); ++i)
885 // if (i->first=="WinHide") continue;
886 // If input type is Void : no recurse
887 //if ( bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo()
890 bbtkBlackBoxDebugMessage("change",2,
892 <<"': status before update = '"
893 <<GetIOStatusString(i->second->GetStatus())
895 i->second->RecursiveExecute();
896 IOStatus t = i->second->GetStatus();
898 bbtkBlackBoxDebugMessage("change",2,
900 <<"': status before process = '"
901 <<GetIOStatusString(i->second->GetStatus())
905 bbtkBlackBoxDebugMessage("process",4,
906 "<= BlackBox::bbUpdateInputs()"
912 //=========================================================================
914 //==================================================================
915 /// Computes the final IOStatus of inputs and outputs after processing
916 void BlackBox::bbComputePostProcessStatus()
918 bbtkBlackBoxDebugMessage("process",4,
919 "=> BlackBox::bbComputePostProcessStatus()"
922 IOStatus new_output_status = UPTODATE;
923 if (bbBoxProcessModeIsAlways()) new_output_status = OUTOFDATE;
925 // Update the input statuses
926 InputConnectorMapType::iterator i;
927 for ( i = bbGetInputConnectorMap().begin();
928 i!= bbGetInputConnectorMap().end(); ++i)
930 IOStatus t = i->second->GetStatus();
931 if (t == OUTOFDATE) new_output_status = OUTOFDATE;
932 // A previously MODIFIED status turns to UPTODATE
933 if (t==MODIFIED) i->second->SetStatus(UPTODATE);
934 bbtkBlackBoxDebugMessage("change",2,
935 "Input '"<<i->first<<"' : "
936 << GetIOStatusString(t) << " -> "
937 << GetIOStatusString(i->second->GetStatus())
940 bbtkBlackBoxDebugMessage("change",2,
941 "New output status : "
942 << GetIOStatusString(new_output_status)
944 // Update the output statuses
945 OutputConnectorMapType::iterator o;
946 for ( o = bbGetOutputConnectorMap().begin();
947 o!= bbGetOutputConnectorMap().end(); ++o)
949 o->second->SetStatus(new_output_status);
952 bbtkBlackBoxDebugMessage("process",4,
953 "<= BlackBox::bbComputePostProcessStatus()"
957 //==================================================================
959 //=========================================================================
960 /// Connects the input <name> to the connection c
961 void BlackBox::bbConnectInput( const std::string& name, Connection* c)
963 bbtkBlackBoxDebugMessage("connection",2,
964 "==> BlackBox::bbConnectInput(\""
965 <<name<<"\","<<c->GetFullName()<<")"
969 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
970 if (i==bbGetInputConnectorMap().end())
972 bbtkError("no input called '"<<name<<"'");
974 i->second->SetConnection(c);
975 // The input *MUST* be set OUTOFDATE to update its input on next execution
976 bbSetStatusAndPropagate(i->second,OUTOFDATE);
978 bbtkBlackBoxDebugMessage("connection",2,
979 "<== BlackBox::bbConnectInput(\""
980 <<name<<"\","<<c->GetFullName()<<")"
984 //=========================================================================
987 //=========================================================================
988 /// Connects the output <name> to the connection c
989 void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
991 bbtkBlackBoxDebugMessage("connection",2,
992 "==> BlackBox::bbConnectOutput(\""<<name<<"\","
993 <<c->GetFullName()<<")"
996 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
997 if (i==bbGetOutputConnectorMap().end())
999 bbtkError("no output called '"<<name<<"'");
1001 i->second->SetConnection(c);
1003 bbtkBlackBoxDebugMessage("connection",2,
1004 "<== BlackBox::bbConnectOutput(\""<<name<<"\","
1005 <<c->GetFullName()<<")"
1009 //=========================================================================
1012 //=========================================================================
1013 /// Disconnects the input <name> from the connection c
1014 void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
1017 bbtkBlackBoxDebugMessage("connection",2,
1018 "==> BlackBox::bbDisconnectInput(\""<<name
1019 <<"\","<<c->GetFullName()<<")"
1025 bbtkBlackBoxDebugMessage("connection",2,"c==0"<<std::endl);
1029 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
1030 if (i==bbGetInputConnectorMap().end())
1032 bbtkError("no input called '"<<name<<"'");
1034 i->second->UnsetConnection(c);
1036 bbtkBlackBoxDebugMessage("connection",2,
1037 "<== BlackBox::bbDisconnectInput(\""<<name
1038 <<"\","<<c->GetFullName()<<")"
1042 //=========================================================================
1045 //=========================================================================
1046 /// Disconnects the output <name> from the connection c
1047 void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
1049 bbtkBlackBoxDebugMessage("connection",2,
1050 "==> BlackBox::bbDisconnectOutput(\""<<name
1051 <<"\","<<c->GetFullName()<<")"
1056 bbtkBlackBoxDebugMessage("connection",2,"c==0"<<std::endl);
1060 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
1061 if (i==bbGetOutputConnectorMap().end())
1063 bbtkError("no output called '"<<name<<"'");
1065 i->second->UnsetConnection(c);
1067 bbtkBlackBoxDebugMessage("connection",2,
1068 "<== BlackBox::bbDisconnectOutput(\""<<name
1069 <<"\","<<c->GetFullName()<<")"
1072 //=========================================================================
1075 //=========================================================================
1077 void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
1079 fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
1081 //=========================================================================
1084 //=========================================================================
1085 std::string BlackBox::bbGetOutputAsString( const std::string &output )
1088 // Looks for the adaptor
1089 if (bbGetOutputType(output).name() != typeid(std::string).name() )
1092 Package::Pointer p = bbGetDescriptor()->GetPackage();
1093 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1095 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1096 BlackBox::Pointer a;
1100 bbGetOutputType(output),
1101 typeid(std::string),
1103 } catch (bbtk::Exception e)
1108 a->bbSetInput("In",bbGetOutput(output));
1110 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1112 v="? (no adaptor found)";
1117 v="? (no factory found)";
1123 v = bbGetOutput(output).unsafe_get<std::string>() ;
1127 //=========================================================================
1129 //=========================================================================
1130 std::string BlackBox::bbGetInputAsString( const std::string &input )
1133 // Looks for the adaptor
1134 if (bbGetInputType(input) != typeid(std::string))
1137 Package::Pointer p = bbGetDescriptor()->GetPackage();
1138 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1140 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1141 BlackBox::Pointer a;
1145 bbGetInputType(input),
1146 typeid(std::string),
1148 }catch (bbtk::Exception e)
1154 a->bbSetInput("In",bbGetInput(input));
1156 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1160 v="? (no adaptor found)";
1165 v="? (no factory found)";
1170 v = bbGetInput(input).unsafe_get<std::string>() ;
1174 //=======================================================================
1176 //=======================================================================
1177 // Replaces substrings "<" by "["
1178 void SubsBrackets ( std::string& s )
1180 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
1181 std::string ss("<");
1182 std::string::size_type pos = 0;
1184 std::string cr("[");
1185 while ( pos != std::string::npos )
1187 // std::cout << "*** find one "<<std::endl;
1188 s.replace(pos,1,cr.c_str(),1);
1189 pos = s.find(ss, pos);
1195 while ( pos != std::string::npos )
1197 // std::cout << "*** find one "<<std::endl;
1198 s.replace(pos,1,cr.c_str(),1);
1199 pos = s.find(ss, pos);
1205 while ( pos != std::string::npos )
1207 // std::cout << "*** find one "<<std::endl;
1208 s.replace(pos,1,cr.c_str(),1);
1209 pos = s.find(ss, pos);
1210 } // std::cout << "AFTER=["<<s<<"]"<<std::endl;
1212 //=======================================================================
1214 //=========================================================================
1215 /// Write Graphviz-dot description in file
1216 void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
1217 BlackBox::Pointer parentblackbox,
1218 int detail, int level,
1219 bool instanceOrtype,
1220 bool relative_link )
1223 InputConnectorMapType::iterator i;
1225 std::string labelStr;
1226 std::string valueStr("");
1229 labelStr = bbGetName() ;
1231 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
1233 labelStr = bbGetName();
1234 labelStr = labelStr + " [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "] ";
1237 SubsBrackets(labelStr);
1240 labelStr = labelStr + " | {{ ";
1241 std::string tempStrTypeName;
1244 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1248 labelStr=labelStr+" | ";
1251 if (instanceOrtype==true)
1253 valueStr = this->bbGetInputAsString(i->first) + " = ";
1255 const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
1256 tempStrTypeName=id->GetTypeName();
1257 SubsBrackets(tempStrTypeName);
1258 std::string Name(i->first);
1260 labelStr=labelStr + "<"+i->first.c_str()+"> " + valueStr + Name.c_str() + " [" + tempStrTypeName.c_str() + "]";
1262 labelStr=labelStr+ " } | {";
1264 OutputConnectorMapType::iterator ii;
1265 for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii )
1269 labelStr=labelStr+" | ";
1272 if (instanceOrtype==true)
1274 valueStr = this->bbGetOutputAsString(ii->first) + " = ";
1276 const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first);
1277 tempStrTypeName=id->GetTypeName();
1278 SubsBrackets(tempStrTypeName);
1279 std::string Name(ii->first);
1281 labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + " ["+tempStrTypeName+"]";
1283 labelStr = labelStr+ " } }" ;
1287 bbWriteDotInputOutputName(ff,true,detail,level);
1288 std::string tmp ( bbGetTypeName() );
1292 url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
1294 url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
1296 fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
1297 // std::cout << labelStr << std::endl;
1300 if (GetThisPointer<BlackBox>()!=parentblackbox){
1301 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1305 Connection* con = i->second->GetConnection();
1307 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1308 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1310 a->bbWriteDotInputOutputName(ff,false,detail,level);
1313 fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1316 b->bbWriteDotInputOutputName(ff,true,detail,level);
1319 fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1321 fprintf(ff,"%s\n",";");
1325 } // if parentblackbox
1327 //=========================================================================
1332 //=========================================================================
1333 void BlackBox::bbShowRelations(BlackBox::Pointer parentblackbox,
1334 int detail, int level
1335 /*,Factory *factory*/ )
1338 if (this->bbGetDescriptor()->GetPackage())
1340 bbtkBlackBoxMessage("help",1,"Black Box '"<<bbGetName()<<"' <"<<
1341 this->bbGetDescriptor()->GetPackage()->GetName()
1342 <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1346 bbtkBlackBoxMessage("help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1351 bbtkBlackBoxMessage("help",1,"Up-to-date ["<<mMaxInputChangeTime<<","
1352 <<mMinOutputChangeTime<<"]"<<std::endl);
1356 bbtkBlackBoxMessage("help",1,"Out-of-date ["<<mMaxInputChangeTime<<","
1357 <<mMinOutputChangeTime<<"]"<<std::endl);
1360 // bbtkBlackBoxMessage("help",1," "<<GetDescription()<<std::endl);
1361 // bbtkBlackBoxMessage("help",1," By : "<<GetAuthor()<<std::endl);
1363 std::vector<std::string> iname;
1364 std::vector<std::string> ivalue;
1365 std::vector<std::string> iconn;
1366 std::vector<std::string> istatus;
1368 InputConnectorMapType::iterator i;
1369 unsigned int namelmax = 0;
1370 unsigned int valuelmax = 0;
1371 // unsigned int connlmax = 0;
1372 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1374 iname.push_back(i->first);
1375 if (iname.back().size()>namelmax) namelmax = iname.back().size();
1376 ivalue.push_back(bbGetInputAsString(i->first));
1377 if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1379 Connection* con = i->second->GetConnection();
1381 s = con->GetOriginalBlackBoxFrom()->bbGetName();
1383 s += con->GetOriginalBlackBoxFromOutput();
1386 istatus.push_back(GetIOStatusString(i->second->GetStatus()));
1388 OutputConnectorMapType::iterator o;
1389 std::vector<std::string> oname;
1390 std::vector<std::string> ovalue;
1391 std::vector<std::vector<std::string> > oconn;
1392 std::vector<std::string> ostatus;
1393 for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o )
1395 oname.push_back(o->first);
1396 if (oname.back().size()>namelmax) namelmax = oname.back().size();
1397 ovalue.push_back(bbGetOutputAsString(o->first));
1398 if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1399 std::vector<std::string> ss;
1400 const std::vector<Connection*>& con
1401 = o->second->GetConnectionVector();
1402 std::vector<Connection*>::const_iterator c;
1403 for (c=con.begin();c!=con.end();++c)
1406 s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1408 s += (*c)->GetOriginalBlackBoxToInput();
1411 oconn.push_back(ss);
1412 ostatus.push_back(GetIOStatusString(o->second->GetStatus()));
1416 bbtkBlackBoxMessage("help",1," * Inputs : "<<std::endl);
1418 bbtkBlackBoxMessage("help",1," * No inputs"<<std::endl);
1420 std::vector<std::string>::iterator i1,i2,i3,i4;
1421 for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin();
1422 i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end();
1423 ++i1,++i2,++i3,++i4)
1425 std::string name(*i1);
1427 name.append(1+namelmax-name.size(),' ');
1428 std::string value(*i2);
1430 value.append(1+valuelmax-value.size(),' ');
1432 bbtkBlackBoxMessage("help",1," '"<<name<<" = '"<<value<<" <-- '"
1435 bbtkBlackBoxMessage("help",1," '"<<name<<" = '"<<value);
1436 bbtkBlackBoxMessage("help",1," ["<<*i4<<"]"<<std::endl);
1440 bbtkBlackBoxMessage("help",1," * Outputs : "<<std::endl);
1442 bbtkBlackBoxMessage("help",1," * No outputs"<<std::endl);
1444 std::vector<std::vector<std::string> >::iterator i5;
1446 for (i1=oname.begin(),i2=ovalue.begin(),i5=oconn.begin(),i4=ostatus.begin();
1447 i1!=oname.end(),i2!=ovalue.end(),i5!=oconn.end(),i4!=ostatus.end();
1448 ++i1,++i2,++i4,++i5)
1450 std::string name(*i1);
1452 name.append(1+namelmax-name.size(),' ');
1453 std::string value(*i2);
1455 value.append(1+valuelmax-value.size(),' ');
1457 bbtkBlackBoxMessage("help",1," '"<<name<<" = '"<<value);
1460 std::string pref = " '"+name+" = '"+value;
1461 for (i3=i5->begin();i3!=i5->end();++i3)
1463 bbtkBlackBoxMessage("help",1,pref<<" --> '"<<*i3<<"'");
1464 pref.replace(0,pref.size(),pref.size(),' ');
1467 bbtkBlackBoxMessage("help",1," ["<<*i4<<"]"<<std::endl);
1471 //=========================================================================
1473 static bool bbmgGlobalProcessingExecutionList = false;
1475 //=========================================================================
1476 void BlackBox::bbGlobalProcessExecutionList()
1478 bbtkDebugMessage("process",3,
1479 "=> BlackBox::bbGlobalProcessExecutionList()"
1481 if (bbmgGlobalProcessingExecutionList)
1483 bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1486 bbmgGlobalProcessingExecutionList = true;
1488 std::set<BlackBox::WeakPointer>::iterator i;
1489 while (bbmgExecutionList.size()>0)
1491 i = bbmgExecutionList.begin();
1492 BlackBox::WeakPointer p = *i;
1493 bbmgExecutionList.erase(i);
1496 bbtkDebugMessage("process",4,
1498 p.lock()->bbGetName()<<"'"<<std::endl);
1499 p.lock()->bbExecute(true);
1503 bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1507 bbmgExecutionList.clear();
1508 bbtkDebugMessage("process",3,
1509 "<= BlackBox::bbGlobalProcessExecutionList()"
1512 bbmgGlobalProcessingExecutionList = false;
1515 //=========================================================================
1517 bool BlackBox::bbGlobalGetSomeBoxExecuting()
1519 return bbmgSomeBoxExecuting;
1522 void BlackBox::bbGlobalSetSomeBoxExecuting(bool b)
1524 bbmgSomeBoxExecuting = b;
1527 void BlackBox::bbGlobalSetFreezeExecution(bool b)
1529 bbmgFreezeExecution = b;
1532 bool BlackBox::bbGlobalGetFreezeExecution()
1534 return bbmgFreezeExecution;
1537 void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1539 bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetName()<<")"<<std::endl);
1540 if (bbmgGlobalProcessingExecutionList)
1542 bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1544 bbmgExecutionList.insert(b);
1548 //=========================================================================
1550 //=========================================================================
1551 void BlackBox::Check(bool recursive)
1553 bbtkBlackBoxMessage("debug",1,"*** Checking"
1554 <<" ... OK"<<std::endl);
1556 //=========================================================================
1561 } // EO namespace bbtk