MM::VOID MM::PoolNodeBehavior::sub(MM::Instance * i,
                                   MM::Machine  * m,
                                   MM::Node     * n,
                                   MM::UINT32     amount)
{
  //in case of instance pool: delete instances
  if(of != MM_NULL)
  {
    MM::Definition * def = i->getDefinition();
    MM::Element * unitDef = def->findDeclaredDefinition(of);
    if(unitDef != MM_NULL &&
       unitDef->instanceof(MM::T_Definition) == MM_TRUE)
    {
      i->destroyInstances(n, m, amount);
    }
  }
    
  //subtract from old value
  MM::INT32 oldValue = i->getOldValue(n);
  oldValue = oldValue - amount;
  i->setOldValue(n, oldValue);
  
  //subtract from new value
  MM::INT32 newValue = i->getNewValue(n);
  newValue = newValue - amount;
  i->setNewValue(n, newValue);

  //check if self is empty, which kills this instance
  if(newValue == 0)
  {
    MM::Name * poolName = n->getName();
    if(poolName->equals((MM::CHAR*)MM::PoolNodeBehavior::SELF_STR,
                      MM::PoolNodeBehavior::SELF_LEN) == MM_TRUE)
    {
      //inform parent instance of the demise of instance
      //MM::Instance * parentInstance = i->getParent();
      //parentInstance->destroyInstance(n, m, i);

      //set the new value of the pool node instance one lower
      MM::Element * decl = i->getDeclaration();
      if(decl->instanceof(MM::T_Node) == MM_TRUE)
      {
        MM::Node * declNode = (MM::Node *) decl;
        //must be a pool node!
        MM::Instance * parent = i->getParent();
        MM::INT32 val = parent->getNewValue(declNode);
        parent->setNewValue(declNode, val-100);
        //NOTE: can't use setDirty because sweeep happens after finalize
        //manually notify sub and has value
        parent->notifyObservers(parent, (MM::VOID*) 100, MM::MSG_SUB_VALUE, declNode);
        parent->notifyObservers(parent, (MM::VOID*)(val-100), MM::MSG_HAS_VALUE, declNode);			 
      }

      i->mark();
    }
  }
}
示例#2
0
MM::VOID MM::Evaluator::step(MM::Transition * tr)
{
  MM::Reflector * r = m->getReflector();
  MM::Instance * i = r->getInstance();
  prepareAll(i);
  MM_printf("STEP LEVEL (%ld nodes): pull all\n", pullAllWork->size());
  stepLevel(tr, pullAllWork);
  MM_printf("STEP LEVEL (%ld nodes): pull any\n", pullAnyWork->size());
  stepLevel(tr, pullAnyWork);
  MM_printf("STEP LEVEL (%ld nodes): push all\n", pushAllWork->size());
  stepLevel(tr, pushAllWork);
  MM_printf("STEP LEVEL (%ld nodes): push any\n", pushAnyWork->size());
  stepLevel(tr, pushAnyWork);
  MM_printf("\n");

  //FIXME: we need the currently active nodes to calculate 'satisfied'
  //clearActiveNodes(i);
  
  finalizeAll(i, tr);

  //create temporary string
  MM::String * str = m->createString(10000);
  
  //stringify transition
  str->clear();
  tr->toString(str);
  str->print();
  
  //stringify state
  i->toString(str);
  str->print();
  str->clear();

  //notify flow
  notifyFlow(tr);

  //notify dirty pool instance values
  i->notifyValues(m);
  //notifyValues(i);

  //clean up instances
  //notify deletions
  //NOTE: pool node instance values might change --> also notified
  i->sweep(m);

  //recycle string
  str->recycle(m);
}
示例#3
0
MM::VOID MM::Evaluator::notifyFlow(MM::Transition * tr)
{
  MM::Vector<MM::Element *> * elements = tr->getElements();
  MM::Vector<MM::Element *>::Iterator eIter = elements->getIterator();
  MM::Element * element;
  
  while(eIter.hasNext() == MM_TRUE)
  {
    element = eIter.getNext();
    /*TODO: improve this --> */
    if(element->instanceof(MM::T_FlowEvent) == MM_TRUE)
    {
      MM::FlowEvent * event = (MM::FlowEvent *) element;
      
	    MM::Instance * instance = event->getInstance();
      MM::Instance * srcInstance = event->getSourceInstance();
      MM::Instance * tgtInstance = event->getTargetInstance();
      MM::Node * srcNode = event->getSourceNode();
      MM::Node * tgtNode = event->getTargetNode();
      MM::UINT32 amount = event->getAmount();
      
	    srcInstance->notifyObservers(srcInstance, (MM::VOID*)amount, MM::MSG_SUB_VALUE, srcNode);
      tgtInstance->notifyObservers(tgtInstance, (MM::VOID*)amount, MM::MSG_ADD_VALUE, tgtNode);

      //hack to notify the instance in which the flow occurred
	    if(srcInstance != tgtInstance)
	    {
		    srcInstance->notifyObservers(srcInstance, (MM::VOID*)amount, MM::MSG_ADD_VALUE, tgtNode);
	      tgtInstance->notifyObservers(tgtInstance, (MM::VOID*)amount, MM::MSG_SUB_VALUE, srcNode);
		  }

	    //let observers of instances know the current value of a pool.
      /*
      if(srcNode->getBehavior()->instanceof(MM::T_PoolNodeBehavior) == MM_TRUE)
      {
        MM::INT32 srcAmount = srcNode->getAmount(srcInstance, m);
        srcInstance->notifyObservers(srcInstance, (MM::VOID*)srcAmount, MM::MSG_HAS_VALUE, srcNode);
      }
      if(tgtNode->getBehavior()->instanceof(MM::T_PoolNodeBehavior) == MM_TRUE)
      {
        MM::INT32 tgtAmount = tgtNode->getAmount(tgtInstance, m);
        tgtInstance->notifyObservers(tgtInstance, (MM::VOID*)tgtAmount, MM::MSG_HAS_VALUE, tgtNode);
      }
      */
    }
	  else if(element->instanceof(MM::T_Event) == MM_TRUE)
	  {
      MM::Event * event = (MM::Event *) element;
      MM::Element * e = event->getElement();
      MM::Instance * i = event->getInstance();
      MM::MESSAGE msg = event->getMessage();
      i->notifyObservers(i, (MM::VOID*)0, msg, e); 
	  }
  }
}
示例#4
0
MM::VOID MM::SourceNodeBehavior::stepPushAll(MM::Node * srcNode,
                                             MM::Instance * srcInstance,
                                             MM::Vector<MM::NodeWorkItem *> * work,
                                             MM::Machine * m,
                                             MM::Transition * tr)
{
  MM::Evaluator * evaluator = m->getEvaluator();
  
  MM::Vector<MM::Element *> es;
  MM::Vector<MM::NodeWorkItem *>::Iterator workIter = work->getIterator();
  MM::BOOLEAN success = MM_TRUE;
  
 // MM::INT32 tempSrcAmount = srcInstance->getValue(srcNode);
  
  MM_printf("STEP PUSH ALL NODE %s (%ld edges)\n",
            srcNode->getName()->getBuffer(),
            work->size());
  
  while(workIter.hasNext() == MM_TRUE)
  {
    MM::NodeWorkItem * workItem = workIter.getNext();
    MM::Edge * edge = workItem->getEdge();
    MM::Exp * exp = edge->getExp();
    MM::Node * tgtNode = workItem->getNode();
    MM::Instance * tgtInstance = workItem->getInstance();
    MM::INT32 val = 0; //evaluated expression
  
    val = evaluateExpression(srcInstance, exp, edge, m);

    val = (val / 100) * 100;
    
    if(val >= 100 &&
       tgtInstance->hasCapacity(tgtNode, val, m) == MM_TRUE)
    {
      //tempSrcAmount -= val;
      MM::FlowEvent * event =
        m->createFlowEvent(srcInstance, srcNode, edge,
                           srcInstance, srcNode, val, tgtInstance, tgtNode);
      es.add(event);
    }
    else
    {
      success = MM_FALSE;
      break;
    }
  }
  
  //if we have computed a succesfull transition, then apply it
  if(success == MM_TRUE)
  {
    MM::Vector<MM::Element *>::Iterator eIter = es.getIterator();
    while(eIter.hasNext() == MM_TRUE)
    {
      //store the transition
      MM::FlowEvent * event = (MM::FlowEvent *) eIter.getNext();
      tr->addElement((MM::Element*)event);
      
      //and apply the flow
      MM::Instance * srcInstance = event->getSourceInstance();
      MM::Instance * tgtInstance = event->getTargetInstance();
      MM::Node * srcNode = event->getSourceNode();
      MM::Node * tgtNode = event->getTargetNode();
      MM::UINT32 flow = event->getAmount();
      MM_printf("Full flow %ld\n", flow);
      
      srcInstance->sub(srcNode, m, flow);
      tgtInstance->add(tgtNode, m, flow);
    }
  }
  else
  {
    //fail
	  MM::Failure * event = m->createFailure(srcInstance, srcNode);
    tr->addElement(event);
	  
	  //clean up
    MM::Vector<MM::Element *>::Iterator eIter = es.getIterator();
    while(eIter.hasNext() == MM_TRUE)
    {
      MM::Element * element = eIter.getNext();
      element->recycle(m);
    }
  }
}