1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.cxx,v $
5 Date: $Date: 2009/06/08 14:50:02 $
6 Version: $Revision: 1.48 $
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 std::string BlackBox::bbGetNameWithParent() const
174 if (bbmParent.lock())
176 return bbmParent.lock()->bbGetNameWithParent() + ":" + bbmName;
183 //=========================================================================
185 //=========================================================================
186 void BlackBox::bbGetHelp(bool full) const
188 bbGetDescriptor()->GetHelp(full);
190 //=========================================================================
193 //=========================================================================
194 bool BlackBox::bbHasInput(const std::string& name) const
196 bbtkBlackBoxDebugMessage("kernel",8,
197 "BlackBox::bbHasInput(\""
200 bool r = ( bbGetDescriptor()->GetInputDescriptorMap().find(name)
201 != bbGetDescriptor()->GetInputDescriptorMap().end());
202 bbtkDebugDecTab("kernel",8);
205 //=========================================================================
208 //=========================================================================
209 bool BlackBox::bbHasOutput(const std::string& name) const
211 bbtkBlackBoxDebugMessage("kernel",8,"BlackBox::bbHasOutput(\""
214 bool r = ( bbGetDescriptor()->GetOutputDescriptorMap().find(name)
215 != bbGetDescriptor()->GetOutputDescriptorMap().end());
216 bbtkDebugDecTab("kernel",8);
219 //=========================================================================
222 //=========================================================================
223 TypeInfo BlackBox::bbGetOutputType( const std::string &name ) const
225 bbtkBlackBoxDebugMessage("kernel",8,
226 "BlackBox::bbGetOutputType(\""
229 TypeInfo r = bbGetDescriptor()->GetOutputDescriptor(name)->GetTypeInfo();
230 bbtkDebugDecTab("kernel",8);
233 //=========================================================================
235 //=========================================================================
236 TypeInfo BlackBox::bbGetInputType( const std::string &name ) const
238 bbtkBlackBoxDebugMessage("kernel",8,
239 "BlackBox::bbGetInputType(\""
242 TypeInfo r = bbGetDescriptor()->GetInputDescriptor(name)->GetTypeInfo();
243 bbtkDebugDecTab("kernel",8);
246 //=========================================================================
249 //=========================================================================
250 void BlackBox::bbAllocateConnectors()
252 bbtkBlackBoxDebugMessage("kernel",8,
253 "BlackBox::bbAllocateConnectors()"
256 MakeBlackBoxPointer(this,true);
258 const BlackBoxDescriptor::InputDescriptorMapType& imap
259 = bbGetDescriptor()->GetInputDescriptorMap();
260 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
261 for ( i = imap.begin(); i != imap.end(); ++i )
263 bbtkBlackBoxDebugMessage("kernel",8,"* Allocate \""<<i->first<<"\""<<std::endl);
264 bbGetInputConnectorMap()[i->second->GetName()]
265 = new BlackBoxInputConnector(GetThisPointer<BlackBox>());
267 const BlackBoxDescriptor::OutputDescriptorMapType& omap
268 = bbGetDescriptor()->GetOutputDescriptorMap();
269 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
270 for ( o = omap.begin(); o != omap.end(); ++o )
272 bbtkBlackBoxDebugMessage("kernel",8,"* Allocate \""<<o->first<<"\""<<std::endl);
273 bbGetOutputConnectorMap()[o->second->GetName()]
274 = new BlackBoxOutputConnector(GetThisPointer<BlackBox>());
278 //=========================================================================
281 //=========================================================================
282 void BlackBox::bbDesallocateConnectors()
284 bbtkBlackBoxDebugMessage("kernel",8,
285 "BlackBox::bbDesallocateConnectors()"
288 InputConnectorMapType::const_iterator i;
289 for ( i = bbGetInputConnectorMap().begin();
290 i != bbGetInputConnectorMap().end(); ++i )
292 bbtkBlackBoxDebugMessage("kernel",8,"* Delete \""<<i->first<<"\""<<std::endl);
295 OutputConnectorMapType::const_iterator o;
296 for ( o = bbGetOutputConnectorMap().begin();
297 o != bbGetOutputConnectorMap().end(); ++o )
299 bbtkBlackBoxDebugMessage("kernel",8,"* Delete \""<<o->first<<"\""<<std::endl);
303 bbtkDebugDecTab("kernel",8);
306 //=========================================================================
309 //=========================================================================
310 void BlackBox::bbCopyIOValues(BlackBox& from)
312 bbtkBlackBoxDebugMessage("kernel",1,
313 "BlackBox::bbCopyIOValues("
314 <<from.bbGetFullName()<<")"
316 // copies the input values
317 const BlackBoxDescriptor::InputDescriptorMapType& imap
318 = bbGetDescriptor()->GetInputDescriptorMap();
319 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
320 for ( i = imap.begin(); i != imap.end(); ++i )
322 if (! i->second->GetCopyConstruct() ) continue;
323 std::string input = i->second->GetName();
324 bbtkBlackBoxDebugMessage("kernel",2,"* Copying input "<<input<<std::endl);
325 this->bbSetInput(input, from.bbGetInput(input) );
327 // copies the output values
328 const BlackBoxDescriptor::OutputDescriptorMapType& omap
329 = bbGetDescriptor()->GetOutputDescriptorMap();
330 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
331 for ( o = omap.begin(); o != omap.end(); ++o )
333 if (! o->second->GetCopyConstruct() ) continue;
334 std::string output = o->second->GetName();
335 bbtkBlackBoxDebugMessage("kernel",2,"* Copying output "<<output<<std::endl);
336 this->bbSetOutput(output, from.bbGetOutput(output) );
339 bbtkDebugDecTab("kernel",9);
342 //=========================================================================
346 //=========================================================================
347 bool BlackBox::bbCanReact() const
349 return ( bbGlobalGetSomeBoxExecuting()
351 || Wx::IsSomeWindowAlive()
355 //=========================================================================
359 //=========================================================================
360 BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const
362 const std::string& p = bbmBoxProcessMode;
364 (p == "P") || (p == "p") ||
365 (p == "Pipeline") || (p == "pipeline") ) return Pipeline;
367 (p == "A") || (p == "a") ||
368 (p == "Always") || (p == "always") ) return Always;
370 (p == "R") || (p == "r") ||
371 (p == "Reactive") || (p == "reactive") ) return Reactive;
374 (p == "F") || (p == "f") ||
375 (p == "Flash") || (p == "flash") ) return Flash;
377 bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
378 <<"' unknown. Possible values : "
379 <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
380 <<"'1'/'A'/'a'/'Always'/'always' | "
381 <<"'2'/'R'/'r'/'Reactive'/'reactive'"
382 // <<"'3'/'F'/'f'/'Flash'/'flash'"
385 //=========================================================================
387 //=========================================================================
388 bool BlackBox::bbBoxProcessModeIsReactive() const
390 return (bbGetBoxProcessModeValue() == Reactive);
392 //=========================================================================
394 //=========================================================================
395 bool BlackBox::bbBoxProcessModeIsAlways() const
397 return (bbGetBoxProcessModeValue() == Always);
399 //=========================================================================
404 //=========================================================================
405 void BlackBox::bbAddOutputObserver(const std::string& output,
406 OutputChangeCallbackType f)
408 bbGetOutputConnector(output).AddChangeObserver(f);
410 //=========================================================================
412 //=========================================================================
413 void BlackBox::bbRemoveOutputObserver(const std::string& output_name,
414 OutputChangeCallbackType f)
416 bbtkError("BlackBox::RemoveChangeObserver NOT IMPLEMENTED");
418 //=========================================================================
421 //=========================================================================
422 void BlackBox::bbSetStatusAndPropagate(BlackBoxInputConnector* c,
425 bbtkBlackBoxDebugMessage("change",5,
426 "=> BlackBox::bbSetStatusAndPropagate(input,"
427 <<GetIOStatusString(s)<<")"
430 if (s==UPTODATE) bbtkError("bbSetStatusAndPropagate with status UPTODATE!");
435 if (bbGetBoxProcessModeValue() == Flash)
441 OutputConnectorMapType::const_iterator o;
442 for ( o = bbGetOutputConnectorMap().begin();
443 o != bbGetOutputConnectorMap().end(); ++o )
445 if (o->second->GetStatus()==UPTODATE)
447 o->second->SetStatus(OUTOFDATE);
448 o->second->SignalChange(GetThisPointer<BlackBox>(),o->first);
452 if ( ( bbBoxProcessModeIsReactive() ||
453 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
456 bbtkBlackBoxDebugMessage("change",2,
457 "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
458 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
460 bbtkBlackBoxDebugMessage("change",5,
461 "<= BlackBox::bbSetStatusAndPropagate(input)"
464 //=========================================================================
467 //=========================================================================
468 void BlackBox::bbSignalOutputModification(bool reaction)
470 bbtkBlackBoxDebugMessage("change",5,
471 "=> BlackBox::bbSignalOutputModification("
475 OutputConnectorMapType::iterator i;
476 for ( i = bbGetOutputConnectorMap().begin();
477 i != bbGetOutputConnectorMap().end(); ++i)
479 // std::cout << "Stat = "
480 //<<GetIOStatusString(i->second->GetStatus())
482 // LG : CANNOT SIGNAL ONLY WHEN UPTODATE
483 // See bbtkSampleOutputObserver
484 // if (i->second->GetStatus()==UPTODATE)
486 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
490 if (reaction) bbGlobalProcessExecutionList();
492 bbtkBlackBoxDebugMessage("change",5,
493 "<= BlackBox::bbSignalOutputModification()"
497 //=========================================================================
498 //=========================================================================
499 void BlackBox::bbSignalOutputModification(const std::string& output,
502 bbtkBlackBoxDebugMessage("change",5,
503 "=> BlackBox::bbSignalOutputModification("
504 <<output<<","<<reaction<<")"
507 OutputConnectorMapType::iterator i =
508 bbGetOutputConnectorMap().find(output);
511 if ( i == bbGetOutputConnectorMap().end() )
513 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
516 // if (i->second->GetStatus()==UPTODATE)
518 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
519 // Has to notify the output "BoxChange" also
520 if (output != "BoxChange")
522 i = bbGetOutputConnectorMap().find("BoxChange");
523 if ( i != bbGetOutputConnectorMap().end() )
525 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
528 if (reaction) bbGlobalProcessExecutionList();
531 bbtkBlackBoxDebugMessage("change",5,
532 "<= BlackBox::bbSignalOutputModification("
537 //=========================================================================
538 //=========================================================================
539 void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
542 bbtkBlackBoxDebugMessage("change",5,
543 "=> BlackBox::bbSignalOutputModification(vector of outputs)"
545 OutputConnectorMapType::iterator i;
546 std::vector<std::string>::const_iterator o;
547 bool changed = false;
548 for (o=output.begin();o!=output.end();++o)
550 // the output "BoxChange" must be signaled **AFTER** all others
551 if (*o == "BoxChange") continue;
552 // Look for the connector
553 i = bbGetOutputConnectorMap().find(*o);
554 if ( i == bbGetOutputConnectorMap().end() )
556 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
559 // if (i->second->GetStatus()==UPTODATE)
561 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
565 // Has to notify the output "BoxChange" also
566 i = bbGetOutputConnectorMap().find("BoxChange");
567 if ( changed && (i != bbGetOutputConnectorMap().end()))
569 // if (i->second->GetStatus()==UPTODATE)
571 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
572 if (reaction) bbGlobalProcessExecutionList();
576 bbtkBlackBoxDebugMessage("change",5,
577 "<= BlackBox::bbSignalOutputModification(vector of outputs)"
581 //=========================================================================
589 //=========================================================================
590 /// Main processing method of the box.
591 void BlackBox::bbExecute(bool force)
593 bbtkBlackBoxDebugMessage("process",2,
594 "=> BlackBox::bbExecute("<<(int)force<<")"
597 // If already executing : return
599 if (bbGetExecuting())
601 bbtkBlackBoxDebugMessage("process",2,
602 " -> already executing : abort"<<std::endl);
607 // If execution frozen : return
608 if (bbGlobalGetFreezeExecution())
610 bbtkBlackBoxDebugMessage("process",2,
611 " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
616 // If force is true then update is triggered even if the box is UPTODATE
617 // if (force) bbSetModifiedStatus();
619 // Calls the main recursive execution method
620 bbRecursiveExecute(Connection::Pointer());
622 bbtkBlackBoxDebugMessage("process",2,
623 "<= BlackBox::bbExecute()"
626 //=========================================================================
628 //=========================================================================
629 void BlackBox::bbInitializeProcessing()
633 bbtkBlackBoxDebugMessage("process",2,"** Initialize processing"
635 this->bbRecursiveInitializeProcessing();
636 bbmInitialized = true;
639 //=========================================================================
641 //=========================================================================
642 void BlackBox::bbFinalizeProcessing()
646 bbtkBlackBoxDebugMessage("process",2,"** Finalize processing"
648 this->bbRecursiveFinalizeProcessing();
649 bbmInitialized = false;
652 //=========================================================================
655 //=========================================================================
656 void BlackBox::bbRecursiveExecute( Connection::Pointer caller )
658 bbtkBlackBoxDebugMessage("process",3,
659 "=> BlackBox::bbRecursiveExecute("
660 <<(caller?caller->GetFullName():"0")<<")"
663 // If already executing : return
664 if (bbGetExecuting())
666 bbtkBlackBoxDebugMessage("process",3,
667 " -> already executing : abort"<<std::endl);
671 // If not initialized do it
672 bbInitializeProcessing();
674 bbSetExecuting(true);
675 bool wasExecuting = bbGlobalGetSomeBoxExecuting();
676 bbGlobalSetSomeBoxExecuting(true);
678 // Creates the window if the black box has one
679 this->bbCreateWindow();
681 // Updates its inputs
682 IOStatus s = bbUpdateInputs();
684 if ( (s != UPTODATE) ||
685 bbBoxProcessModeIsAlways() )
687 // Displays the window (WxBlackbox)
688 // bbShowWindow(caller);
690 // Actual processing (virtual)
694 // Update the I/O statuses
695 bbComputePostProcessStatus();
699 // Test output status...
700 OutputConnectorMapType::iterator o;
701 for ( o = bbGetOutputConnectorMap().begin();
702 o!= bbGetOutputConnectorMap().end(); ++o)
704 if (o->second->GetStatus() != UPTODATE)
706 bbtkWarning("BlackBox::bbRecursiveExecute: "
707 <<"all inputs are Up-to-date but output '"
708 <<o->first<<"' is Out-of-date ???");
712 bbtkBlackBoxDebugMessage("process",3," -> Up-to-date : nothing to do"
716 // Shows the window if the black box has one
717 this->bbShowWindow();
720 bbtkBlackBoxDebugMessage("process",3,
721 "<= BlackBox::bbRecursiveExecute()"
724 bbSetExecuting(false);
725 bbGlobalSetSomeBoxExecuting(wasExecuting);
730 //=========================================================================
736 //=========================================================================
737 IOStatus BlackBox::bbUpdateInputs()
739 bbtkBlackBoxDebugMessage("process",4,
740 "=> BlackBox::bbUpdateInputs()"
743 IOStatus s = UPTODATE;
745 InputConnectorMapType::iterator i;
746 for ( i = bbGetInputConnectorMap().begin();
747 i!= bbGetInputConnectorMap().end(); ++i)
749 // if (i->first=="WinHide") continue;
750 // If input type is Void : no recurse
751 //if ( bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo()
754 bbtkBlackBoxDebugMessage("change",2,
756 <<"': status before update = '"
757 <<GetIOStatusString(i->second->GetStatus())
759 i->second->RecursiveExecute();
760 IOStatus t = i->second->GetStatus();
762 bbtkBlackBoxDebugMessage("change",2,
764 <<"': status before process = '"
765 <<GetIOStatusString(i->second->GetStatus())
769 bbtkBlackBoxDebugMessage("process",4,
770 "<= BlackBox::bbUpdateInputs()"
776 //=========================================================================
778 //==================================================================
779 void BlackBox::bbComputePostProcessStatus()
781 bbtkBlackBoxDebugMessage("process",4,
782 "=> BlackBox::bbComputePostProcessStatus()"
785 IOStatus new_output_status = UPTODATE;
786 if (bbBoxProcessModeIsAlways()) new_output_status = OUTOFDATE;
788 // Update the input statuses
789 InputConnectorMapType::iterator i;
790 for ( i = bbGetInputConnectorMap().begin();
791 i!= bbGetInputConnectorMap().end(); ++i)
793 IOStatus t = i->second->GetStatus();
794 if (t == OUTOFDATE) new_output_status = OUTOFDATE;
795 // A previously MODIFIED status turns to UPTODATE
796 if (t==MODIFIED) i->second->SetStatus(UPTODATE);
797 bbtkBlackBoxDebugMessage("change",2,
798 "Input '"<<i->first<<"' : "
799 << GetIOStatusString(t) << " -> "
800 << GetIOStatusString(i->second->GetStatus())
803 bbtkBlackBoxDebugMessage("change",2,
804 "New output status : "
805 << GetIOStatusString(new_output_status)
807 // Update the output statuses
808 OutputConnectorMapType::iterator o;
809 for ( o = bbGetOutputConnectorMap().begin();
810 o!= bbGetOutputConnectorMap().end(); ++o)
812 o->second->SetStatus(new_output_status);
815 bbtkBlackBoxDebugMessage("process",4,
816 "<= BlackBox::bbComputePostProcessStatus()"
820 //==================================================================
822 //=========================================================================
823 void BlackBox::bbConnectInput( const std::string& name, Connection* c)
825 bbtkBlackBoxDebugMessage("connection",2,
826 "==> BlackBox::bbConnectInput(\""
827 <<name<<"\","<<c->GetFullName()<<")"
831 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
832 if (i==bbGetInputConnectorMap().end())
834 bbtkError("no input called '"<<name<<"'");
836 i->second->SetConnection(c);
837 // The input *MUST* be set OUTOFDATE to update its input on next execution
838 bbSetStatusAndPropagate(i->second,OUTOFDATE);
840 bbtkBlackBoxDebugMessage("connection",2,
841 "<== BlackBox::bbConnectInput(\""
842 <<name<<"\","<<c->GetFullName()<<")"
846 //=========================================================================
849 //=========================================================================
850 void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
852 bbtkBlackBoxDebugMessage("connection",2,
853 "==> BlackBox::bbConnectOutput(\""<<name<<"\","
854 <<c->GetFullName()<<")"
857 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
858 if (i==bbGetOutputConnectorMap().end())
860 bbtkError("no output called '"<<name<<"'");
862 i->second->SetConnection(c);
864 bbtkBlackBoxDebugMessage("connection",2,
865 "<== BlackBox::bbConnectOutput(\""<<name<<"\","
866 <<c->GetFullName()<<")"
870 //=========================================================================
873 //=========================================================================
874 void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
877 bbtkBlackBoxDebugMessage("connection",2,
878 "==> BlackBox::bbDisconnectInput(\""<<name
879 <<"\","<<c->GetFullName()<<")"
885 bbtkBlackBoxDebugMessage("connection",2,"c==0"<<std::endl);
889 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
890 if (i==bbGetInputConnectorMap().end())
892 bbtkError("no input called '"<<name<<"'");
894 i->second->UnsetConnection(c);
896 bbtkBlackBoxDebugMessage("connection",2,
897 "<== BlackBox::bbDisconnectInput(\""<<name
898 <<"\","<<c->GetFullName()<<")"
902 //=========================================================================
905 //=========================================================================
906 void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
908 bbtkBlackBoxDebugMessage("connection",2,
909 "==> BlackBox::bbDisconnectOutput(\""<<name
910 <<"\","<<c->GetFullName()<<")"
915 bbtkBlackBoxDebugMessage("connection",2,"c==0"<<std::endl);
919 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
920 if (i==bbGetOutputConnectorMap().end())
922 bbtkError("no output called '"<<name<<"'");
924 i->second->UnsetConnection(c);
926 bbtkBlackBoxDebugMessage("connection",2,
927 "<== BlackBox::bbDisconnectOutput(\""<<name
928 <<"\","<<c->GetFullName()<<")"
931 //=========================================================================
955 //=========================================================================
956 void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
958 fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
960 //=========================================================================
963 //=========================================================================
964 std::string BlackBox::bbGetOutputAsString( const std::string &output )
967 // Looks for the adaptor
968 if (bbGetOutputType(output).name() != typeid(std::string).name() )
971 Package::Pointer p = bbGetDescriptor()->GetPackage();
972 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
974 Factory::Pointer f = p->GetFactorySet().begin()->lock();
979 bbGetOutputType(output),
982 } catch (bbtk::Exception e)
987 a->bbSetInput("In",bbGetOutput(output));
989 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
991 v="? (no adaptor found)";
996 v="? (no factory found)";
1002 v = bbGetOutput(output).unsafe_get<std::string>() ;
1006 //=========================================================================
1008 //=========================================================================
1009 std::string BlackBox::bbGetInputAsString( const std::string &input )
1012 // Looks for the adaptor
1013 if (bbGetInputType(input) != typeid(std::string))
1016 Package::Pointer p = bbGetDescriptor()->GetPackage();
1017 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1019 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1020 BlackBox::Pointer a;
1024 bbGetInputType(input),
1025 typeid(std::string),
1027 }catch (bbtk::Exception e)
1033 a->bbSetInput("In",bbGetInput(input));
1035 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1039 v="? (no adaptor found)";
1044 v="? (no factory found)";
1049 v = bbGetInput(input).unsafe_get<std::string>() ;
1053 //=======================================================================
1055 //=======================================================================
1056 // Replaces substrings "<" by "["
1057 void SubsBrackets ( std::string& s )
1059 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
1060 std::string ss("<");
1061 std::string::size_type pos = 0;
1063 std::string cr("[");
1064 while ( pos != std::string::npos )
1066 // std::cout << "*** find one "<<std::endl;
1067 s.replace(pos,1,cr.c_str(),1);
1068 pos = s.find(ss, pos);
1074 while ( pos != std::string::npos )
1076 // std::cout << "*** find one "<<std::endl;
1077 s.replace(pos,1,cr.c_str(),1);
1078 pos = s.find(ss, pos);
1084 while ( pos != std::string::npos )
1086 // std::cout << "*** find one "<<std::endl;
1087 s.replace(pos,1,cr.c_str(),1);
1088 pos = s.find(ss, pos);
1089 } // std::cout << "AFTER=["<<s<<"]"<<std::endl;
1091 //=======================================================================
1093 //=========================================================================
1094 /// Write Graphviz-dot description in file
1095 void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
1096 BlackBox::Pointer parentblackbox,
1097 int detail, int level,
1098 bool instanceOrtype,
1099 bool relative_link )
1102 InputConnectorMapType::iterator i;
1104 std::string labelStr;
1105 std::string valueStr("");
1108 labelStr = bbGetName() ;
1110 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
1112 labelStr = bbGetName();
1113 labelStr = labelStr + " [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "] ";
1116 SubsBrackets(labelStr);
1119 labelStr = labelStr + " | {{ ";
1120 std::string tempStrTypeName;
1123 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1127 labelStr=labelStr+" | ";
1130 if (instanceOrtype==true)
1132 valueStr = this->bbGetInputAsString(i->first) + " = ";
1134 const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
1135 tempStrTypeName=id->GetTypeName();
1136 SubsBrackets(tempStrTypeName);
1137 std::string Name(i->first);
1139 labelStr=labelStr + "<"+i->first.c_str()+"> " + valueStr + Name.c_str() + " [" + tempStrTypeName.c_str() + "]";
1141 labelStr=labelStr+ " } | {";
1143 OutputConnectorMapType::iterator ii;
1144 for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii )
1148 labelStr=labelStr+" | ";
1151 if (instanceOrtype==true)
1153 valueStr = this->bbGetOutputAsString(ii->first) + " = ";
1155 const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first);
1156 tempStrTypeName=id->GetTypeName();
1157 SubsBrackets(tempStrTypeName);
1158 std::string Name(ii->first);
1160 labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + " ["+tempStrTypeName+"]";
1162 labelStr = labelStr+ " } }" ;
1166 bbWriteDotInputOutputName(ff,true,detail,level);
1167 std::string tmp ( bbGetTypeName() );
1171 url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
1173 url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
1175 fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
1176 // std::cout << labelStr << std::endl;
1179 if (GetThisPointer<BlackBox>()!=parentblackbox){
1180 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1184 Connection* con = i->second->GetConnection();
1186 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1187 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1189 a->bbWriteDotInputOutputName(ff,false,detail,level);
1192 fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1195 b->bbWriteDotInputOutputName(ff,true,detail,level);
1198 fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1200 fprintf(ff,"%s\n",";");
1204 } // if parentblackbox
1206 //=========================================================================
1211 //=========================================================================
1212 void BlackBox::bbPrintHelp(BlackBox::Pointer parentblackbox,
1213 int detail, int level
1214 /*,Factory *factory*/ )
1217 if (this->bbGetDescriptor()->GetPackage())
1219 bbtkBlackBoxMessage("help",1,"Black Box '"<<bbGetName()<<"' <"<<
1220 this->bbGetDescriptor()->GetPackage()->GetName()
1221 <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1225 bbtkBlackBoxMessage("help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1230 bbtkBlackBoxMessage("help",1,"Up-to-date ["<<mMaxInputChangeTime<<","
1231 <<mMinOutputChangeTime<<"]"<<std::endl);
1235 bbtkBlackBoxMessage("help",1,"Out-of-date ["<<mMaxInputChangeTime<<","
1236 <<mMinOutputChangeTime<<"]"<<std::endl);
1239 // bbtkBlackBoxMessage("help",1," "<<GetDescription()<<std::endl);
1240 // bbtkBlackBoxMessage("help",1," By : "<<GetAuthor()<<std::endl);
1242 std::vector<std::string> iname;
1243 std::vector<std::string> ivalue;
1244 std::vector<std::string> iconn;
1245 std::vector<std::string> istatus;
1247 InputConnectorMapType::iterator i;
1248 unsigned int namelmax = 0;
1249 unsigned int valuelmax = 0;
1250 // unsigned int connlmax = 0;
1251 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1253 iname.push_back(i->first);
1254 if (iname.back().size()>namelmax) namelmax = iname.back().size();
1255 ivalue.push_back(bbGetInputAsString(i->first));
1256 if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1258 Connection* con = i->second->GetConnection();
1260 s = con->GetOriginalBlackBoxFrom()->bbGetName();
1262 s += con->GetOriginalBlackBoxFromOutput();
1265 istatus.push_back(GetIOStatusString(i->second->GetStatus()));
1267 OutputConnectorMapType::iterator o;
1268 std::vector<std::string> oname;
1269 std::vector<std::string> ovalue;
1270 std::vector<std::vector<std::string> > oconn;
1271 std::vector<std::string> ostatus;
1272 for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o )
1274 oname.push_back(o->first);
1275 if (oname.back().size()>namelmax) namelmax = oname.back().size();
1276 ovalue.push_back(bbGetOutputAsString(o->first));
1277 if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1278 std::vector<std::string> ss;
1279 const std::vector<Connection*>& con
1280 = o->second->GetConnectionVector();
1281 std::vector<Connection*>::const_iterator c;
1282 for (c=con.begin();c!=con.end();++c)
1285 s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1287 s += (*c)->GetOriginalBlackBoxToInput();
1290 oconn.push_back(ss);
1291 ostatus.push_back(GetIOStatusString(o->second->GetStatus()));
1295 bbtkBlackBoxMessage("help",1," * Inputs : "<<std::endl);
1297 bbtkBlackBoxMessage("help",1," * No inputs"<<std::endl);
1299 std::vector<std::string>::iterator i1,i2,i3,i4;
1300 for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin();
1301 i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end();
1302 ++i1,++i2,++i3,++i4)
1304 std::string name(*i1);
1306 name.append(1+namelmax-name.size(),' ');
1307 std::string value(*i2);
1309 value.append(1+valuelmax-value.size(),' ');
1311 bbtkBlackBoxMessage("help",1," '"<<name<<" = '"<<value<<" <-- '"
1314 bbtkBlackBoxMessage("help",1," '"<<name<<" = '"<<value);
1315 bbtkBlackBoxMessage("help",1," ["<<*i4<<"]"<<std::endl);
1319 bbtkBlackBoxMessage("help",1," * Outputs : "<<std::endl);
1321 bbtkBlackBoxMessage("help",1," * No outputs"<<std::endl);
1323 std::vector<std::vector<std::string> >::iterator i5;
1325 for (i1=oname.begin(),i2=ovalue.begin(),i5=oconn.begin(),i4=ostatus.begin();
1326 i1!=oname.end(),i2!=ovalue.end(),i5!=oconn.end(),i4!=ostatus.end();
1327 ++i1,++i2,++i4,++i5)
1329 std::string name(*i1);
1331 name.append(1+namelmax-name.size(),' ');
1332 std::string value(*i2);
1334 value.append(1+valuelmax-value.size(),' ');
1336 bbtkBlackBoxMessage("help",1," '"<<name<<" = '"<<value);
1339 std::string pref = " '"+name+" = '"+value;
1340 for (i3=i5->begin();i3!=i5->end();++i3)
1342 bbtkBlackBoxMessage("help",1,pref<<" --> '"<<*i3<<"'");
1343 pref.replace(0,pref.size(),pref.size(),' ');
1346 bbtkBlackBoxMessage("help",1," ["<<*i4<<"]"<<std::endl);
1350 //=========================================================================
1369 static bool bbmgGlobalProcessingExecutionList = false;
1371 //=========================================================================
1372 void BlackBox::bbGlobalProcessExecutionList()
1374 bbtkDebugMessage("process",3,
1375 "=> BlackBox::bbGlobalProcessExecutionList()"
1377 if (bbmgGlobalProcessingExecutionList)
1379 bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1382 bbmgGlobalProcessingExecutionList = true;
1384 std::set<BlackBox::WeakPointer>::iterator i;
1385 while (bbmgExecutionList.size()>0)
1387 i = bbmgExecutionList.begin();
1388 BlackBox::WeakPointer p = *i;
1389 bbmgExecutionList.erase(i);
1392 bbtkDebugMessage("process",4,
1394 p.lock()->bbGetName()<<"'"<<std::endl);
1395 p.lock()->bbExecute(true);
1399 bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1403 bbmgExecutionList.clear();
1404 bbtkDebugMessage("process",3,
1405 "<= BlackBox::bbGlobalProcessExecutionList()"
1408 bbmgGlobalProcessingExecutionList = false;
1411 //=========================================================================
1413 bool BlackBox::bbGlobalGetSomeBoxExecuting()
1415 return bbmgSomeBoxExecuting;
1418 void BlackBox::bbGlobalSetSomeBoxExecuting(bool b)
1420 bbmgSomeBoxExecuting = b;
1423 void BlackBox::bbGlobalSetFreezeExecution(bool b)
1425 bbmgFreezeExecution = b;
1428 bool BlackBox::bbGlobalGetFreezeExecution()
1430 return bbmgFreezeExecution;
1433 void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1435 bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetName()<<")"<<std::endl);
1436 if (bbmgGlobalProcessingExecutionList)
1438 bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1440 bbmgExecutionList.insert(b);
1444 //=========================================================================
1446 //=========================================================================
1447 void BlackBox::Check(bool recursive)
1449 bbtkBlackBoxMessage("debug",1,"*** Checking"
1450 <<" ... OK"<<std::endl);
1452 //=========================================================================
1457 } // EO namespace bbtk