/* # --------------------------------------------------------------------- # # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image # pour la SantÈ) # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton # Previous Authors : Laurent Guigues, Jean-Pierre Roux # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil # # This software is governed by the CeCILL-B license under French law and # abiding by the rules of distribution of free software. You can use, # modify and/ or redistribute the software under the terms of the CeCILL-B # license as circulated by CEA, CNRS and INRIA at the following URL # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html # or in the file LICENSE.txt. # # As a counterpart to the access to the source code and rights to copy, # modify and redistribute granted by the license, users are provided only # with a limited warranty and the software's author, the holder of the # economic rights, and the successive licensors have only limited # liability. # # The fact that you are presently reading this means that you have had # knowledge of the CeCILL-B license and that you accept its terms. # ------------------------------------------------------------------------ */ /*========================================================================= Program: bbtk Module: $RCSfile: bbtkConnection.cxx,v $ Language: C++ Date: $Date: 2012/11/16 08:49:01 $ Version: $Revision: 1.22 $ =========================================================================*/ /** *\file *\brief Class bbtk::Connection */ #include "bbtkConnection.h" #include "bbtkFactory.h" #include "bbtkBlackBox.h" #include "bbtkMessageManager.h" #include "bbtkBlackBoxOutputConnector.h" #define bbtkCMessage(key,level,mess) \ bbtkMessage(key,level,"["< Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""<bbGetName()<<"\",\""<bbGetName()<<"\",\""< Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""< Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""<bbHasOutput(output) ) { bbtkError("The box \""<bbGetTypeName()<< "\" has no output \""<bbHasInput(input) ) { bbtkError("The box \""<bbGetTypeName()<< "\" has no input \""<bbGetInputConnectorMap().find(input)->second->IsConnected()) { bbtkError("The input \""<bbGetName() <<"\" is already connected"); } // std::string t1 ( from->bbGetOutputType(output).name() ); // std::string t2 ( to->bbGetInputType(input).name() ); // if //( t1 != t2 ) if ( from->bbGetOutputType(output) != to->bbGetInputType(input) ) { if ( from->bbGetOutputType(output) == typeid(Data) ) { bbtkWarning("Connection: '"<bbGetName()<<"."<() <<"> : type compatibility with '" <bbGetName()<<"."<bbGetInputType(input) == typeid(Data) ) { bbtkDebugMessage("kernel",8," -> '"<()<<" : can receive any data" <bbGetName() + "." + output + "-" + to->bbGetName() + "." + input; mAdaptor = mFactory.lock() ->NewAdaptor(from->bbGetOutputType(output), to->bbGetInputType(input), name); if (!mAdaptor) { bbtkError("did not find any <" <bbGetOutputType(output)) <<"> to <" <bbGetInputType(input)) <<"> adaptor"); } } } mFrom = from; mOriginalFrom = from; mTo = to; mOriginalTo = to; mInput = mOriginalInput = input; mOutput = mOriginalOutput = output; // Lock this pointer !!! //Pointer p = MakePointer(this,true); from->bbConnectOutput(output,this); to->bbConnectInput(input,this); from->bbGetOutputConnector(output).AddChangeObserver(boost::bind(&bbtk::Connection::OnOutputChange,this, _1, _2, _3)); bbtkDebugMessage("connection",1,"<== Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""<bbGetName()<<"\",\""<bbGetName()<<"\",\""< Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""<bbGetName()<<"\",\""<bbGetName()<<"\",\""< Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""< Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""<bbHasOutput(output) ) { bbtkError("The box \""<bbGetTypeName()<< "\" has no output \""<bbHasInput(input) ) { bbtkError("The box \""<bbGetTypeName()<< "\" has no input \""<bbGetInputConnectorMap().find(input)->second->IsConnected()) { bbtkError("The input \""<bbGetName() <<"\" is already connected"); } // std::string t1 ( from->bbGetOutputType(output).name() ); // std::string t2 ( to->bbGetInputType(input).name() ); // if //( t1 != t2 ) if ( from->bbGetOutputType(output) != to->bbGetInputType(input) ) { if ( from->bbGetOutputType(output) == typeid(Data) ) { bbtkWarning("Connection '" <bbGetName()<<"."<() <<"> : type compatibility with '" <bbGetName()<<"."<bbGetInputType(input) == typeid(Data) ) { bbtkDebugMessage("kernel",8," -> '"<()<<" : can receive any data" <bbConnectOutput(output,this); to->bbConnectInput(input,this); from->bbGetOutputConnector(output).AddChangeObserver(boost::bind(&bbtk::Connection::OnOutputChange,this, _1, _2, _3)); bbtkDebugMessage("connection",1,"<== Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""< Connection(\"" <bbGetName()<<"\",\""<bbGetName()<<"\",\""< ~Connection()" <bbDisconnectOutput(mOutput,this); // GetThisPointer()); mFrom.reset(); } else { bbtkInternalError("~Connection() : invalid initial box pointer"); } if (mTo!=0) { mTo->bbDisconnectInput(mInput,this);// GetThisPointer()); mTo.reset(); } else { bbtkInternalError("~Connection() : invalid final box pointer"); } bbtkCDebugMessage("object",4, "<== ~Connection()" < Connection::RecursiveExecute()" <bbGetExecuting()) { bbtkDebugMessage("process",3, " -> "<bbGetName() <<" already executing : abort"<bbRecursiveExecute(GetThisPointer()); TransferData(); // Transfer status IOStatus s = MODIFIED; if ( mFrom->bbGetOutputConnector(mOutput).GetStatus() == OUTOFDATE) { s = OUTOFDATE; } mTo->bbGetInputConnector(mInput).SetStatus(s); bbtkCDebugMessage("process",4, " --> '"<bbGetName()<<"."<bbGetInputConnector(mInput)<<"] " <<"' new status '" <bbSetInput("In",mFrom->bbGetOutput(mOutput),false); mAdaptor->bbExecute(); // LG : Connection Update does not set mTo as modified mTo->bbSetInput(mInput, mAdaptor->bbGetOutput("Out"),false); } // If no adaptor but source type is an any and target is not an any else if ( mFromAny && (! mToAny) ) { bbtkCDebugMessage("data",3, " * Source type is an " <() <<" which contains a <" <bbGetOutput(mOutput).type()) <<">"<bbGetInputType(mInput)) <<">"<bbGetOutput(mOutput).type() == typeid(void)) { bbtkCDebugMessage("data",3, " -> Source is void : nothing to transfer!"<bbGetOutput(mOutput) .contains( mTo->bbGetInputType(mInput) ) ) { bbtkCDebugMessage("data",3, " -> Equal types : transfer ok"<bbSetInput( mInput, mFrom->bbGetOutput(mOutput), false); } else { // 2) Look for an adaptor bbtk::BlackBox::Pointer adaptor; try { adaptor = mFactory.lock() ->NewAdaptor(mFrom->bbGetOutput(mOutput).type(), mTo->bbGetInputType(mInput), ""); } catch (...) { } if (adaptor) { bbtkCDebugMessage("data",3," -> Adaptor found : using it" <bbSetInput("In",mFrom->bbGetOutput(mOutput),false); adaptor->bbExecute(); // LG : Connection Update does not set mTo as modified mTo->bbSetInput(mInput, adaptor->bbGetOutput("Out"),false); // adaptor->bbDelete(); } // 3) If no adaptor found but the any content is a pointer // and target type is also a pointer : we try run-time cast else if ( (mFrom->bbGetOutput(mOutput).contains_pointer()) && (mTo->bbGetDescriptor()->GetInputDescriptor(mInput) ->IsPointerType()) ) { bbtkCDebugMessage("data",3, " -> No adaptor found but source and target types are both pointers : trying up or down cast"<bbGetOutput(mOutput) .get_pointer_to(mTo->bbGetInput(mInput).pointed_type()); if (!nptr) { bbtkError("Connection '" <bbGetOutput(mOutput).type()) <<"> to <" <bbGetInputType(mInput)) <<"> : no adaptor available and run-time up and down cast failed"); } mTo->bbBruteForceSetInputPointer(mInput, nptr, false); } // 4) Nothing worked : error else { bbtkError("Connection '"<bbGetOutput(mOutput).type()) <<"> to <" <bbGetInputType(mInput))<<">"); } } } // EO : mFromAny && ! mToAny // Default case : types are the same; we use simple get-set else { // LG : Connection Update does not set mTo as modified mTo->bbSetInput(mInput, mFrom->bbGetOutput(mOutput),false); } } //================================================================== //================================================================== /// From.Output change propagation void Connection::OnOutputChange(bbtk::BlackBox::Pointer, const std::string&, IOStatus status) { bbtkCDebugMessage("change",2, "==> Connection::OnOutputChange(" <bbGetInputConnectorMap().find("In")->second; mAdaptor->bbSetStatusAndPropagate(ac,status); } mTo->bbSetStatusAndPropagate( mTo->bbGetInputConnectorMap().find(mInput)->second, status); } //================================================================== //================================================================== std::string Connection::GetFullName() const { if (mFrom && mTo) { std::string res = mFrom->bbGetName()+"."+mOutput+"--" +mTo->bbGetName()+"."+mInput; if ((!mOriginalFrom.expired()) && (!mOriginalTo.expired()) && ((mFrom!=mOriginalFrom.lock())||(mTo!=mOriginalTo.lock()))) { res += "("+mOriginalFrom.lock()->bbGetName() +"."+mOriginalOutput+"--" + mOriginalTo.lock()->bbGetName()+"."+mOriginalInput+")"; } return res; } return "***Invalid Connection***"; } //================================================================== //================================================================== void Connection::Check() const { bbtkMessage("debug",1,"** Checking Connection "<<(void*)this<<" [" <bbGetName()<bbHasOutput(mOutput)) { bbtkError("** Checking Connection "<<(void*)this <<" ["<bbGetName()<<" does not have output '" <bbGetOutputConnectorMap().find(mOutput); if (i== mFrom->bbGetOutputConnectorMap().end()) { bbtkError("** Checking Connection "<<(void*)this <<" ["<bbGetName()<<" output '" <::const_iterator j; /* for (j = i->second->GetConnectionVector().begin(); j != i->second->GetConnectionVector().end(); ++j) { if ((*j)==this) break; } */ j = find(i->second->GetConnectionVector().begin(), i->second->GetConnectionVector().end(), this); if (j==i->second->GetConnectionVector().end()) { bbtkError("** Checking Connection "<<(void*)this <<" ["<bbGetName() <<" does not point to this connection"); } bbtkMessage("debug",2," - From : This connection is in OutputConnector connection vector"<bbGetName()<bbGetDescriptor() << std::endl; // std::cout << mTo->bbGetDescriptor()->GetTypeName() << std::endl; // mTo->bbGetName(); bbtkMessage("debug",2," - To : "<bbGetName()<bbHasInput(mInput)) { bbtkError("** Checking Connection "<<(void*)this <<" ["<bbGetName()<<" does not have input '" <bbGetInputConnectorMap().find(mInput); if (i== mTo->bbGetInputConnectorMap().end()) { bbtkError("** Checking Connection "<<(void*)this <<" ["<bbGetName()<<" input '" <second->GetConnection()==0) { bbtkError("** Checking Connection "<<(void*)this <<" ["<bbGetName() <<" does not point to this connection"); } bbtkMessage("debug",2," - To : This connection is in InputConnector connection vector"<