_value->incrRef();
}
-void AnyInputPort::put(Any *data)
+void AnyInputPort::releaseDataUnsafe()
{
- YACS::BASES::AutoLocker<YACS::BASES::Mutex> lock(&_mutex);
if(_value)
_value->decrRef();
+ _value = nullptr;
+}
+
+void AnyInputPort::releaseData()
+{
+ YACS::BASES::AutoLocker<YACS::BASES::Mutex> lock(&_mutex);
+ releaseDataUnsafe();
+}
+
+void AnyInputPort::put(Any *data)
+{
+ YACS::BASES::AutoLocker<YACS::BASES::Mutex> lock(&_mutex);
+ releaseDataUnsafe();
_value=data;
- if (_value) {
- _value->incrRef();
- DEBTRACE("value ref count: " << _value->getRefCnt());
- }
+ if (_value)
+ {
+ _value->incrRef();
+ DEBTRACE("value ref count: " << _value->getRefCnt());
+ }
}
bool AnyInputPort::isEmpty()
void exRestoreInit();
Any *getValue() const { return _value; }
int getIntValue() const { return _value ? _value->getIntValue():0; }
+ void releaseData() override;
void put(Any *data);
void *get() const;
virtual std::string getAsString();
InputPort *clone(Node *newHelder) const;
std::string dump();
virtual std::string typeName() {return "YACS__ENGINE__AnyInputPort";}
+ protected:
+ void releaseDataUnsafe();
protected:
Any *_value;
private:
iterS=end->getNode()->_father;
InPort *currentPortI=end;
+ bool isLoopProofLink(true),isFirstTurn(true);
while(iterS!=lwstCmnAnctr)
{
+ if(!isFirstTurn && iterS->isLoop())// isFirstTurn is a way to filter special inputs like nbBranches, splitPort... These special inputs are loopProof -> they must not be realeased by ForEachLoop::exUpdateState
+ isLoopProofLink=false;
iterS->buildDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
iterS=iterS->_father;
+ isFirstTurn=false;
}
bool ret=(pO.first)->addInPort(currentPortI);
- end->edNotifyReferencedBy(pO.second);
+ end->edNotifyReferencedBy(pO.second,isLoopProofLink);
return ret;
}
void edRemoveLink(OutPort *start, InPort *end) throw(Exception);
void edRemoveLink(OutGate *start, InGate *end) throw(Exception);
virtual bool isRepeatedUnpredictablySeveralTimes() const { return false; }
+ virtual bool isLoop() const { return false; }
virtual std::list<Node *> edGetDirectDescendants() const = 0;
virtual void removeRecursivelyRedundantCL();
std::list<ElementaryNode *> getRecursiveConstituents() const;
return _outOfScopeBackLink!=0;
}
-void ConditionInputPort::edNotifyReferencedBy(OutPort *fromPort)
+void ConditionInputPort::edNotifyReferencedBy(OutPort *fromPort, bool isLoopProof)
{
if(!((ComposedNode*)(_node))->isInMyDescendance(fromPort->getNode()))
{
throw Exception("ConditionInputPort::edNotifyReferenced : already linked from outside");
_outOfScopeBackLink=fromPort;
}
- InputPort::edNotifyReferencedBy(fromPort);
+ InputPort::edNotifyReferencedBy(fromPort,isLoopProof);
}
void ConditionInputPort::edNotifyDereferencedBy(OutPort *fromPort)
put((Any*)data);
}
-void ConditionInputPort::put(Any *data) throw(ConversionException)
+void ConditionInputPort::releaseData()
{
if(_value)
_value->decrRef();
+ _value=nullptr;
+}
+
+void ConditionInputPort::put(Any *data) throw(ConversionException)
+{
+ ConditionInputPort::releaseData();
_value=data;
_value->incrRef();
}
void exSaveInit();
void exRestoreInit();
bool isLinkedOutOfScope() const;
- void edNotifyReferencedBy(OutPort *fromPort);
+ void edNotifyReferencedBy(OutPort *fromPort, bool isLoopProof) override;
void edNotifyDereferencedBy(OutPort *fromPort);
void *get() const;
virtual void put(const void *data) throw(ConversionException);
void put(Any *data) throw(ConversionException);
+ void releaseData() override;
std::string dump();
virtual std::string getAsString();
protected:
DEBTRACE("notifyObserver2 " << event << object );
}
+void Observer::notifyObserverFromClone(Node *originalInstance, const std::string& event, Node *clonedInstanceGeneratingEvent)
+{
+ DEBTRACE("notifyObserverFromClone " << event << originalInstance );
+}
+
Dispatcher* Dispatcher::_singleton = 0;
Dispatcher::~Dispatcher()
}
}
+void Dispatcher::dispatchFromClone(Node *originalInstance, const std::string& event, Node *clonedInstanceGeneratingEvent)
+{
+ std::pair<Node*,std::string> key(originalInstance,event);
+ std::map< std::pair<Node*,std::string> , std::set<Observer*> >::const_iterator it(_observers.find(key));
+ if(it!=_observers.end())
+ {
+ for(std::set<Observer*>::const_iterator iter=(*it).second.begin();iter!=(*it).second.end();iter++)
+ {
+ (*iter)->notifyObserverFromClone(originalInstance,event,clonedInstanceGeneratingEvent);
+ }
+ }
+}
+
void Dispatcher::addObserver(Observer* observer,Node* object, const std::string& event)
{
_observers[std::pair<Node*,std::string>(object,event)].insert(observer);
public:
virtual void notifyObserver(Node* object,const std::string& event);
virtual void notifyObserver2(Node* object,const std::string& event, void *something);
+ virtual void notifyObserverFromClone(Node *originalInstance, const std::string& event, Node *clonedInstanceGeneratingEvent);
virtual ~Observer();
};
public:
virtual void dispatch(Node* object,const std::string& event);
virtual void dispatch2(Node* object,const std::string& event, void *something);
+ virtual void dispatchFromClone(Node *originalInstance, const std::string& event, Node *clonedInstanceGeneratingEvent);
virtual void addObserver(Observer* observer,Node* object,const std::string& event);
virtual void removeObserver(Observer* observer,Node* object,const std::string& event);
virtual void printObservers();
if(portToSet)//portToSet==0 in case of portToSet==_splitterNode._dataPortToDispatch of ForEach
{
portToSet->put((const void *)val);
- portToSet->edNotifyReferencedBy(0);//This is to indicate that somewhere somebody deals with this inputport
+ portToSet->edNotifyReferencedBy(nullptr,false);//This is to indicate that somewhere somebody deals with this inputport
//even if no direct physical link exists. This exclusively for _execNodes[branchNb]::init on the next turn of loop.
+ //false is put as 2nd parameter to tell to portToSet, do not touch to the data in case of squeezeMemory.
}
}
}
//! For the moment false is returned : impovement about it coming soon.
bool isPlacementPredictableB4Run() const;
void edRemoveChild(Node *node) throw(Exception);
+ bool isLoop() const override { return true; }
virtual bool edAddChild(Node *DISOWNnode) throw(Exception);
std::list<Node *> edGetDirectDescendants() const;
std::list<InputPort *> getSetOfInputPort() const;
Node * getFinalizeNode();
int getMaxLevelOfParallelism() const;
void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap);
+ virtual void cleanDynGraph();
protected:
void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView);
void buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView);
virtual void checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(Exception);
protected:
- void cleanDynGraph();
void prepareInputsFromOutOfScope(int branchNb);
void putValueOnBranch(Any *val, unsigned branchId, bool first);
TypeOfNode getIdentityOfNotifyerNode(const Node *node, unsigned& id);
std::string input_port_name = (*iter1)->getName();
// Get Port Name in master node
InputPort * master_port = getInputPort(input_port_name);
- for (std::set<OutPort *>::const_iterator itt=master_port->_backLinks.begin(); itt!=master_port->_backLinks.end();itt++)
+ for (auto itt : master_port->_backLinks)
{
// Connect dataflow
- getProc()->edAddDFLink((*itt),(*iter1));
+ getProc()->edAddDFLink(itt.first,(*iter1));
}
}
_passedData->checkLevel2(_execOutGoingPorts[0]);
_passedData->assignAlreadyDone(_execVals);
}
+ // clean inputs data coming from the outside in _node
+ set< InPort * > portsToSetVals=getAllInPortsComingFromOutsideOfCurrentScope();
+ for(auto iter : portsToSetVals)
+ {
+ InputPort *curPortCasted=(InputPort *) iter;//Cast granted by ForEachLoop::buildDelegateOf(InPort)
+ if(!curPortCasted->canSafelySqueezeMemory())// this can appear strange ! if not safelySqueeze -> release. Nevertheless it is true.
+ curPortCasted->releaseData(); // these input ports have been incremented with InputPort::put into DynParaLoop::prepareInputsFromOutOfScope. So they can be released now.
+ }
}
catch(YACS::Exception& ex)
{
else if(_state == YACS::ACTIVATED)
{//more elements to do and loop still activated
_execIds[id]=_execCurrentId;
- node->init(false);
int posInAbs(_execCurrentId);
if(_passedData)
posInAbs=_passedData->toAbsId(_execCurrentId);
_splitterNode.putSplittedValueOnRankTo(posInAbs,id,false);
+ //forwardExecStateToOriginalBody(node);
+ node->init(false);
_execCurrentId++;
node->exUpdateState();
- forwardExecStateToOriginalBody(node);
+ //forwardExecStateToOriginalBody(node);
_nbOfEltConsumed++;
}
else
if(level==0)return;
DynParaLoop::resetState(level);
_execCurrentId=0;
- //Note: cleanDynGraph is not a virtual method (must be called from ForEachLoop object)
cleanDynGraph();
}
void assignPassedResults(const std::vector<unsigned int>& passedIds, const std::vector<SequenceAny *>& passedOutputs, const std::vector<std::string>& nameOfOutputs);
#endif
const TypeCode* getOutputPortType(const std::string& portName)const;
+ void cleanDynGraph() override;
protected:
Node *simpleClone(ComposedNode *father, bool editionOnly=true) const;
void checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
void getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception);
protected:
- void cleanDynGraph();
void pushAllSequenceValues();
void createOutputOutOfScopeInterceptors(int branchNb);
void prepareSequenceValues(int sizeOfSamples);
#include "InPort.hxx"
#include "OutPort.hxx"
#include "ComposedNode.hxx"
+
#include <iostream>
+#include <algorithm>
using namespace YACS::ENGINE;
using namespace std;
void InPort::edRemoveAllLinksLinkedWithMe() throw(YACS::Exception)
{
- set<OutPort *> temp(_backLinks);//edRemoveLink called after causes invalidation of set iterator.
- for(set<OutPort *>::iterator iter=temp.begin();iter!=temp.end();iter++)
+ set< std::pair<OutPort *,bool> > temp(_backLinks);//edRemoveLink called after causes invalidation of set iterator.
+ for(auto iter : temp)
{
set<OutPort *> trueBackOutputs;
- (*iter)->getAllRepresented(trueBackOutputs);
- for(set<OutPort *>::iterator iter2=trueBackOutputs.begin();iter2!=trueBackOutputs.end();iter2++)
- _node->getRootNode()->edRemoveLink(*iter2,this);
+ iter.first->getAllRepresented(trueBackOutputs);
+ for( auto iter2 : trueBackOutputs )
+ _node->getRootNode()->edRemoveLink(iter2,this);
}
_backLinks.clear();
modified();
//! Returns \b physical backlinks \b NOT user backlinks.
std::set<OutPort *> InPort::edSetOutPort() const
{
- return _backLinks;
+ std::set<OutPort *> ret;
+ for( auto iter : _backLinks )
+ ret.insert(iter.first);
+ return ret;
+}
+
+bool InPort::canSafelySqueezeMemory() const
+{
+ if(!isBackLinked())
+ return false;
+ for(auto bl : _backLinks)
+ {
+ if(!bl.second)
+ return false;
+ }
+ return true;
}
-void InPort::edNotifyReferencedBy(OutPort *fromPort)
+/*!
+ * \param [in] isLoopProof - Tells if the data coming from \a fromPort will be send again in case of \a this is initialized. This value is
+ * important if \a this is an InPort of a Node contained directly or not inside a Loop, ForEachLoop, OptimizerLoop.
+ * In this case, to optimize memory consumption (see squeezeMemory method), we need to know if data coming from \a fromPort
+ * will be generated again in case.
+ * If true (the default) it means that for that link is a link loop proof so no need to take care. If false, the link is not loop proof so
+ * event in the context of agressive memory management the data can't be safely released.
+ */
+void InPort::edNotifyReferencedBy(OutPort *fromPort, bool isLoopProof)
{
- _backLinks.insert(fromPort);
+ auto it(std::find_if(_backLinks.begin(),_backLinks.end(),[fromPort](const std::pair<OutPort *,bool>& p){ return p.first==fromPort; }));
+ if(it!=_backLinks.end())
+ _backLinks.erase(it);
+ _backLinks.insert(std::pair<OutPort *,bool>(fromPort,isLoopProof));
modified();
}
void InPort::edNotifyDereferencedBy(OutPort *fromPort)
{
- _backLinks.erase(fromPort);
+ auto it(std::find_if(_backLinks.begin(),_backLinks.end(),[fromPort](const std::pair<OutPort *,bool>& p){ return p.first==fromPort; }));
+ if(it!=_backLinks.end())
+ _backLinks.erase(it);
modified();
}
virtual InPort *getPublicRepresentant() { return this; }
virtual int edGetNumberOfLinks() const;
virtual std::set<OutPort *> edSetOutPort() const;
+ bool canSafelySqueezeMemory() const;
+ bool isBackLinked() const { return !_backLinks.empty(); }
virtual ~InPort();
virtual std::string typeName() {return "YACS__ENGINE__InPort";}
protected:
InPort(const InPort& other, Node *newHelder);
InPort(const std::string& name, Node *node, TypeCode* type);
void edRemoveAllLinksLinkedWithMe() throw(Exception);
- virtual void edNotifyReferencedBy(OutPort *fromPort);
+ virtual void edNotifyReferencedBy(OutPort *fromPort, bool isLoopProof = true);
virtual void edNotifyDereferencedBy(OutPort *fromPort);
virtual void getAllRepresentants(std::set<InPort *>& repr) const;
protected:
- std::set<OutPort *> _backLinks;
+ std::set< std::pair<OutPort *,bool> > _backLinks;
};
}
}
put((YACS::ENGINE::Any *)data);
}
+void InPropertyPort::releaseData()
+{
+ if(_property_data)
+ _property_data->decrRef();
+ _property_data = nullptr;
+}
+
void
InPropertyPort::put(YACS::ENGINE::Any *data)
{
std::string value = ((*seq_data)[i]["value"])->getStringValue();
exNewPropertyValue(key, value);
}
-
- if(_property_data)
- _property_data->decrRef();
+ InPropertyPort::releaseData();
_property_data = data;
_property_data->incrRef();
DEBTRACE("value ref count: " << _property_data->getRefCnt());
virtual void *get() const;
virtual void put(const void *data) throw(ConversionException);
virtual void put(YACS::ENGINE::Any *data);
-
+ void releaseData() override;
protected:
InPropertyPort(const InPropertyPort& other, Node *newHelder);
InPropertyPort(const std::string& name, Node *node, TypeCode* type, bool canBeNull = false);
throw Exception("ProxyPort::clone : internal error - should never happened");
}
-void ProxyPort::edNotifyReferencedBy(OutPort *fromPort)
+void ProxyPort::edNotifyReferencedBy(OutPort *fromPort, bool isLoopProof)
{
- _port->edNotifyReferencedBy(fromPort);
+ _port->edNotifyReferencedBy(fromPort,isLoopProof);
}
void ProxyPort::edNotifyDereferencedBy(OutPort *fromPort)
return _port->get();
}
+void ProxyPort::releaseData()
+{
+ _port->releaseData();
+}
+
void ProxyPort::put(const void *data) throw(ConversionException)
{
_port->put(data);
virtual bool isEmpty();
virtual void *get() const = 0;
+ virtual void releaseData() = 0;
virtual void put(const void *data) throw(ConversionException) = 0;
virtual std::string dump();
virtual std::string getHumanRepr();
protected:
InputPort(const InputPort& other, Node *newHelder);
InputPort(const std::string& name, Node *node, TypeCode* type, bool canBeNull = false);
+ void releaseDataUnsafe();
protected:
Any *_initValue;
std::string _stringRef;
void edRemoveAllLinksLinkedWithMe() throw(Exception);
InputPort *clone(Node *newHelder) const;
- void edNotifyReferencedBy(OutPort *fromPort);
+ void edNotifyReferencedBy(OutPort *fromPort, bool isLoopProof = true) override;
void edNotifyDereferencedBy(OutPort *fromPort);
std::set<OutPort *> edSetOutPort() const;
#ifdef NOCOVARIANT
#endif
void *get() const;
virtual void put(const void *data) throw(ConversionException) ;
+ void releaseData() override;
int edGetNumberOfLinks() const;
bool isIntermediate() const { return true; }
void exRestoreInit();
throw Exception("InputPort4DF2DS::clone : internal error");
}
-void InputPort4DF2DS::put(Any *data)
+void InputPort4DF2DS::releaseData()
{
if(_data)
_data->decrRef();
+ _data = nullptr;
+}
+
+void InputPort4DF2DS::put(Any *data)
+{
+ InputPort4DF2DS::releaseData();
_data=data;
_data->incrRef();
}
public:
InputPort4DF2DS(DFToDSForLoop *node, TypeCode* type);
void getAllRepresentants(std::set<InPort *>& repr) const;
+ void releaseData() override;
void put(const void *data) throw(ConversionException);
InputPort *clone(Node *newHelder) const;
void *get() const throw(Exception);
//Node* DISOWNnode is a SWIG notation to indicate that the ownership of the node is transfered to C++
Node *edSetNode(Node *DISOWNnode);
virtual bool edAddChild(Node *DISOWNnode) throw(Exception);
+ bool isLoop() const override { return true; }
Node *edRemoveNode();
virtual void checkBasicConsistency() const throw(Exception);
//! Returns the port which value is used to take decision about the continuation of the loop.
// Every node has an InPropertyPort
_inPropertyPort = new InPropertyPort("__InPropertyPort__Node__YACS_", this, Runtime::_tc_propvec);
+ _eventReceiver=const_cast<Node *>(&other);
}
Node::~Node()
void Node::sendEvent(const std::string& event)
{
DEBTRACE("Node::sendEvent " << event);
- Dispatcher* disp=Dispatcher::getDispatcher();
- disp->dispatch(this,event);
+ Dispatcher *disp(Dispatcher::getDispatcher());
+ if(!_eventReceiver)
+ {
+ disp->dispatch(this,event);
+ }
+ else
+ {
+ disp->dispatchFromClone(_eventReceiver,event,this);
+ }
}
//! emit notification to all observers registered with the dispatcher
int _numId;
std::string _implementation;
std::map<std::string,std::string> _propertyMap;
+ Node *_eventReceiver=nullptr;
protected:
Node(const std::string& name);
Node(const Node& other, ComposedNode *father);
OutPort *getOutPort(const std::string& name) const throw(Exception);
OutputPort *getOutputPort(const std::string& name) const throw(Exception);
YACS::Event finalize();
-
protected:
virtual YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst);
void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView);
{
}
+void TestElemInputPort::releaseData()
+{
+ stringstream msg;
+ msg << "Not implemented (" << __FILE__ << ":" << __LINE__ << ")";
+ throw Exception(msg.str());
+}
+
void TestElemInputPort::put(const void *data) throw(ConversionException)
{
cerr << _name << endl;
public:
TestElemInputPort(const std::string& name, Node *node, TypeCode* type);
TestElemInputPort(const TestElemInputPort& other, Node *newHelder);
+ void releaseData() override;
void put(const void *data) throw(ConversionException);
InputPort *clone(Node *newHelder) const;
void *get() const throw(Exception);
return new InputToyPort(*this,newHelder);
}
-void InputToyPort::put(Any *data)
+void InputToyPort::releaseData()
{
if(_data)
_data->decrRef();
+ _data=nullptr;
+}
+
+void InputToyPort::put(Any *data)
+{
+ InputToyPort::releaseData();
_data=data;
_data->incrRef();
}
InputPort::edRemoveManInit();
}
-void InputLimitPort::put(Any *data)
+void InputLimitPort::releaseData()
{
if(_data)
_data->decrRef();
+ _data=nullptr;
+}
+
+void InputLimitPort::put(Any *data)
+{
+ InputLimitPort::releaseData();
_data=data;
_data->incrRef();
}
public:
InputToyPort(const InputToyPort& other, Node *newHelder);
InputToyPort(const std::string& name, Node *node);
+ void releaseData() override;
void put(const void *data) throw(ConversionException);
InputPort *clone(Node *newHelder) const;
bool edIsManuallyInitialized() const;
bool edIsManuallyInitialized() const;
void *get() const throw(Exception);
void edRemoveManInit();
+ void releaseData() override;
void put(Any *data);
~InputLimitPort();
Any *getAny() { return _data; }
}
}
+void InputCorbaPort::releaseData()
+{//do nothing - to be implemented
+}
+
void InputCorbaPort::put(CORBA::Any *data) throw (ConversionException)
{
#ifdef REFCNT
void edRemoveManInit();
virtual void put(const void *data) throw(ConversionException);
void put(CORBA::Any *data) throw (ConversionException);
+ void releaseData() override;
InputPort *clone(Node *newHelder) const;
void *get() const throw(Exception);
virtual bool isEmpty();
put((YACS::ENGINE::Any *)data);
}
-void InputCppPort::put(YACS::ENGINE::Any *data) throw(ConversionException)
+void InputCppPort::releaseData()
{
if(_data)
_data->decrRef();
+ _data=nullptr;
+}
+
+void InputCppPort::put(YACS::ENGINE::Any *data) throw(ConversionException)
+{
+ releaseData();
_data=data;
_data->incrRef();
DEBTRACE("value ref count: " << _data->getRefCnt());
void edRemoveManInit();
virtual void put(const void *data) throw(ConversionException);
void put(YACS::ENGINE::Any *data) throw(ConversionException);
+ void releaseData() override;
InputPort *clone(Node *newHelder) const;
virtual YACS::ENGINE::Any * getCppObj() const;
void *get() const throw(Exception);
commonRemoteLoadPart3(reqNode,objContainer,isInitializeRequested);
}
-PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father)
+PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father),_autoSqueeze(other._autoSqueeze)
{
_implementation=IMPL_NAME;
{
_errorDetails=ex.what();
throw;
}
+ if(_autoSqueeze)
+ squeezeMemoryRemote();
}
//
if(!CORBA::is_nil(_pynode))
_errorDetails=ex.what();
throw;
}
-
+ if(_autoSqueeze)
+ squeezeMemory();
DEBTRACE( "-----------------End PyNode::outputs-----------------" );
}
DEBTRACE( "++++++++++++++ End PyNode::execute: " << getName() << " ++++++++++++++++++++" );
}
+void PythonNode::squeezeMemorySafe()
+{
+ AutoGIL agil;
+ if(_mode==PythonNode::REMOTE_NAME)
+ this->squeezeMemoryRemote();
+ else
+ this->squeezeMemory();
+}
+
+void PythonNode::squeezeMemory()
+{
+ for(auto p : _setOfInputPort)
+ {
+ PyDict_DelItemString(_context,p->getName().c_str());
+ InputPyPort *p2(static_cast<InputPyPort *>(p));
+ if(p2->canSafelySqueezeMemory())
+ p2->put(Py_None);
+ }
+ for(auto p : _setOfOutputPort)
+ {
+ PyDict_DelItemString(_context,p->getName().c_str());
+ OutputPyPort *p2(static_cast<OutputPyPort *>(p));
+ p2->putWithoutForward(Py_None);
+ }
+}
+
+void PythonNode::squeezeMemoryRemote()
+{
+ for(auto p : _setOfInputPort)
+ {
+ InputPyPort *p2(static_cast<InputPyPort *>(p));
+ if(p2->canSafelySqueezeMemory())
+ p2->put(Py_None);
+ }
+ for(auto p : _setOfOutputPort)
+ {
+ OutputPyPort *p2(static_cast<OutputPyPort *>(p));
+ p2->putWithoutForward(Py_None);
+ }
+}
+
std::string PythonNode::getContainerLog()
{
return PythonEntry::GetContainerLog(_mode,_container,this);
PythonNode* cloneNode(const std::string& name);
virtual std::string typeName() { return "YACS__ENGINE__PythonNode"; }
void applyDPLScope(ComposedNode *gfn);
+ void setSqueezeStatus(bool sqStatus) { _autoSqueeze=sqStatus; }
+ bool getSqueezeStatus() const { return _autoSqueeze; }
+ void squeezeMemorySafe();
+ protected:
+ void squeezeMemory();
+ void squeezeMemoryRemote();
public:
static const char KIND[];
static const char IMPL_NAME[];
static const char REMOTE_NAME[];
static const char DPL_INFO_NAME[];
protected:
+ bool _autoSqueeze = false;
Engines::PyScriptNode_var _pynode;
};
void releasePyObj(PyObject* data)
{
+ if(!data)
+ return ;
DEBTRACE( "data refcnt: " << data->ob_refcnt );
if (PyObject_HasAttrString(data, (char*)"_is_a"))
{
put((PyObject *)data);
}
-void InputPyPort::put(PyObject *data) throw(ConversionException)
+void InputPyPort::releaseDataUnsafe()
{
- InterpreterUnlocker l;
releasePyObj(_data);
Py_XDECREF(_data);
+ _data = nullptr;
+}
+
+void InputPyPort::releaseData()
+{
+ InterpreterUnlocker l;
+ InputPyPort::releaseDataUnsafe();
+}
+
+void InputPyPort::put(PyObject *data) throw(ConversionException)
+{
+ InterpreterUnlocker l;
+ InputPyPort::releaseDataUnsafe();
_data = data;
_stringRef="";
Py_INCREF(_data);
put((PyObject *)data);
}
-void OutputPyPort::put(PyObject *data) throw(ConversionException)
+void OutputPyPort::putWithoutForward(PyObject *data) throw(ConversionException)
{
- InputPort *p;
DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
#ifdef _DEVDEBUG_
PyObject_Print(data,stderr,Py_PRINT_RAW);
_data = data;
Py_INCREF(_data);
//no registerPyObj : we steal the output reference of the node
+}
+
+void OutputPyPort::put(PyObject *data) throw(ConversionException)
+{
+ putWithoutForward(data);
DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt );
OutputPort::put(data);
}
bool edIsManuallyInitialized() const;
void edRemoveManInit();
virtual void put(const void *data) throw(ConversionException);
+ void releaseData() override;
void put(PyObject *data) throw(ConversionException);
InputPort *clone(Node *newHelder) const;
//special typedef PyObj used in SWIG to increment ref count on output
virtual std::string typeName() {return "YACS__ENGINE__InputPyPort";}
virtual std::string valToStr();
virtual void valFromStr(std::string valstr);
-
+ protected:
+ void releaseDataUnsafe();
protected:
PyObject* _data;
PyObject* _initData;
OutputPyPort(const OutputPyPort& other, Node *newHelder);
~OutputPyPort();
virtual void put(const void *data) throw(ConversionException);
+ void putWithoutForward(PyObject *data) throw(ConversionException);
void put(PyObject *data) throw(ConversionException);
OutputPort *clone(Node *newHelder) const;
virtual PyObject * get() const;
_data = data;
}
+void InputXmlPort::releaseData()
+{//nothing because _data has no ref counter
+}
+
bool InputXmlPort::isEmpty()
{
return _data.empty();
void edRemoveManInit();
virtual void put(const void *data) throw (ConversionException);
void put(const char *data) throw (ConversionException);
+ void releaseData() override;
InputPort *clone(Node *newHelder) const;
virtual const char * getXml() const;
void *get() const throw(Exception);