public synchronized Address<? extends Node> getOrCreateNodeByRecipe(RecipeTraceInfo recipeTrace) { final ReteNodeRecipe recipe = recipeTrace.getRecipe(); Address<? extends Node> result = getNodesByRecipe().get(recipe); if (result != null) { // NODE ALREADY CONSTRUCTED FOR RECIPE, only needs to add trace if (getRecipeTraces().add(recipeTrace)) result.getNodeCache().assignTraceInfo(recipeTrace); } else { // No node for this recipe object - but equivalent recipes still reusable Collection<ReteNodeRecipe> sameClassRecipes = getSameClassRecipes(recipe); for (ReteNodeRecipe knownRecipe : sameClassRecipes) { if (equivalentRecipes(recipe, knownRecipe)) { // FOUND EQUIVALENT RECIPE result = getNodesByRecipe().get(knownRecipe); getNodesByRecipe().put(recipe, result); result.getNodeCache().assignTraceInfo(recipeTrace); break; } } if (result == null) { // MUST INSTANTIATE NEW NODE FOR RECIPE final Node freshNode = instantiateNodeForRecipe(recipeTrace, recipe, sameClassRecipes); result = reteContainer.makeAddress(freshNode); } } return result; }
/** * Internal message delivery method. * * @pre threads > 0 */ private void sendUpdate( Address<? extends Receiver> receiver, Direction direction, Tuple updateElement) { ReteContainer affectedContainer = receiver.getContainer(); synchronized (globalTerminationCriteria) { long newCriterion = affectedContainer.sendUpdateToLocalAddress(receiver, direction, updateElement); terminationCriterion(affectedContainer, newCriterion); } }
/** * Sends multiple update messages atomically to the receiver node, indicating a newly found or * lost partial matching. The node may reside in any of the containers associated with this * network. To be called from a user thread during construction. * * @pre: structuralChangeLock MUST be grabbed by the sequence (but not necessarily this thread, as * the sequence may span through network calls, that's why it's not enforced here ) * @return the value of the target container's clock at the time when the message was accepted * into its message queue */ public void sendConstructionUpdates( Address<? extends Receiver> receiver, Direction direction, Collection<Tuple> updateElements) { // structuralChangeLock.lock(); if (threads > 0) sendUpdates(receiver, direction, updateElements); else receiver .getContainer() .sendUpdatesToLocalAddressSingleThreaded(receiver, direction, updateElements); // structuralChangeLock.unlock(); }
/** * Internal message delivery method. * * @pre threads > 0 */ private void sendUpdates( Address<? extends Receiver> receiver, Direction direction, Collection<Tuple> updateElements) { if (updateElements.isEmpty()) return; ReteContainer affectedContainer = receiver.getContainer(); synchronized (globalTerminationCriteria) { long newCriterion = affectedContainer.sendUpdatesToLocalAddress(receiver, direction, updateElements); terminationCriterion(affectedContainer, newCriterion); } }
/** * Severs connection between a supplier and a receiver node, regardless which container they are * in. Not to be called remotely, because this method enforces the structural lock. * * @param supplier * @param receiver * @param desynchronise indicates whether the current contents of the supplier should be * subtracted from the receiver */ public void disconnectRemoteNodes( Address<? extends Supplier> supplier, Address<? extends Receiver> receiver, boolean desynchronise) { try { if (threads > 0) structuralChangeLock.lock(); receiver.getContainer().disconnectRemoteNodes(supplier, receiver, desynchronise); } finally { if (threads > 0) structuralChangeLock.unlock(); } }
/** * Internal message delivery method for single-threaded operation * * @pre threads == 0 */ private void sendUpdateSingleThreaded( Address<? extends Receiver> receiver, Direction direction, Tuple updateElement) { ReteContainer affectedContainer = receiver.getContainer(); affectedContainer.sendUpdateToLocalAddressSingleThreaded(receiver, direction, updateElement); }