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(); } } }
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); }
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); } } }
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); } } }