/* DripBack creation function */ snet_stream_t *SNetDripBack( snet_stream_t *input, snet_info_t *info, int location, snet_variant_list_t *back_patterns, snet_expr_list_t *guards, snet_startup_fun_t box_a) { snet_stream_t *output; node_t *node; dripback_arg_t *darg; snet_locvec_t *locvec; int detlevel; trace(__func__); detlevel = SNetDetSwapLevel(0); locvec = SNetLocvecGet(info); SNetLocvecFeedbackEnter(locvec); output = SNetStreamCreate(0); node = SNetNodeNew(NODE_dripback, location, &input, 1, &output, 1, SNetNodeDripBack, SNetStopDripBack, SNetTermDripBack); darg = NODE_SPEC(node, dripback); /* fill in the node argument */ darg->input = input; darg->output = output; darg->back_patterns = back_patterns; darg->guards = guards; darg->stopping = 0; /* Create the instance network */ darg->instance = SNetNodeStreamCreate(node); SNetSubnetIncrLevel(); darg->dripback = (*box_a)(darg->instance, info, location); SNetSubnetDecrLevel(); STREAM_DEST(darg->dripback) = node; SNetNodeTableAdd(darg->dripback); /* Create one self-referencing stream. */ darg->selfref = SNetNodeStreamCreate(node); STREAM_DEST(darg->selfref) = node; SNetNodeTableAdd(darg->selfref); darg->entity = SNetEntityCreate( ENTITY_fbdisp, location, locvec, "<feedback>", NULL, (void*)darg); SNetLocvecFeedbackLeave(locvec); SNetDetSwapLevel(detlevel); return output; }
/* Allocate a new stream */ snet_stream_t *SNetStreamCreate(int capacity) { snet_stream_t *stream; trace(__func__); stream = SNetNewAlign(snet_stream_t); STREAM_FROM(stream) = NULL; STREAM_DEST(stream) = NULL; return stream; }
/* Open a descriptor to an output stream. * * The source landing which opens the stream is determined by parameter 'prev'. * The new descriptor holds a pointer to a landing which instantiates * the destination node as determined by the stream parameter 'stream'. * * Special cases: * (1) Dispatchers should create an additional landing for a future collector * and push this landing onto a stack of future landings. * (2) Collectors should retrieve their designated landing from this stack * and verify that it is theirs. */ snet_stream_desc_t *SNetStreamOpen( snet_stream_t *stream, snet_stream_desc_t *prev) { snet_stream_desc_t *desc; trace(__func__); desc = SNetNewAlign(snet_stream_desc_t); DESC_STREAM(desc) = stream; desc->source = prev->landing; desc->refs = 1; SNetFifoInit(&desc->fifo); switch (NODE_TYPE(stream->dest)) { case NODE_filter: case NODE_nameshift: case NODE_output: desc->landing = SNetNewLanding(DESC_DEST(desc), prev, LAND_siso); DESC_LAND_SPEC(desc, siso)->outdesc = NULL; break; case NODE_box: SNetNewBoxLanding(desc, prev); break; case NODE_parallel: SNetNewParallelLanding(desc, prev); break; case NODE_star: SNetNewStarLanding(desc, prev); break; case NODE_split: SNetNewSplitLanding(desc, prev); break; case NODE_feedback: SNetNewFeedbackLanding(desc, prev); break; case NODE_dripback: SNetNewDripBackLanding(desc, prev); break; case NODE_sync: desc->landing = SNetNewLanding(STREAM_DEST(stream), prev, LAND_sync); SNetSyncInitDesc(desc, stream); break; case NODE_zipper: /* Init the landing state of a fused sync-star node */ desc->landing = SNetNewLanding(STREAM_DEST(stream), prev, LAND_zipper); DESC_LAND_SPEC(desc, zipper)->outdesc = NULL; DESC_LAND_SPEC(desc, zipper)->head = NULL; break; case NODE_collector: /* Collectors receive the previously created landing from the stack */ desc->landing = SNetPopLanding(prev); assert(desc->landing); assert(desc->landing->type == LAND_collector); assert(DESC_NODE(desc) == STREAM_DEST(stream)); assert(desc->landing->refs > 0); break; case NODE_observer: desc->landing = SNetNewLanding(DESC_DEST(desc), prev, LAND_observer); DESC_LAND_SPEC(desc, observer)->outdesc = NULL; DESC_LAND_SPEC(desc, observer)->oid = 0; break; case NODE_observer2: desc->landing = SNetPopLanding(prev); assert(desc->landing); assert(desc->landing->type == LAND_empty); break; case NODE_input: case NODE_identity: case NODE_garbage: default: desc->landing = NULL; assert(0); break; } /* if (SNetVerbose() && SNetNodeGetWorkerCount() <= 1) { printf("%s: %s, %s\n", __func__, SNetNodeName(desc->landing->node), SNetLandingName(desc->landing)); } */ return desc; }
/* Deallocate a stream, but remember it's destination node. */ void SNetStopStream(snet_stream_t *stream, fifo_t *fifo) { SNetFifoPut(fifo, STREAM_DEST(stream)); SNetStreamDestroy(stream); }
/* Feedback creation function */ snet_stream_t *SNetFeedback( snet_stream_t *input, snet_info_t *info, int location, snet_variant_list_t *back_patterns, snet_expr_list_t *guards, snet_startup_fun_t box_a) { snet_stream_t *output; node_t *node; feedback_arg_t *farg; snet_locvec_t *locvec; int detlevel; trace(__func__); if (SNetFeedbackDeterministic()) { return SNetDripBack(input, info, location, back_patterns, guards, box_a); } detlevel = SNetDetSwapLevel(0); locvec = SNetLocvecGet(info); SNetLocvecFeedbackEnter(locvec); input = SNetRouteUpdate(info, input, location); if (SNetDistribIsNodeLocation(location)) { output = SNetStreamCreate(0); node = SNetNodeNew(NODE_feedback, &input, 1, &output, 1, SNetNodeFeedback, SNetStopFeedback, SNetTermFeedback); farg = NODE_SPEC(node, feedback); /* fill in the node argument */ farg->input = input; farg->output = output; farg->back_patterns = back_patterns; farg->guards = guards; farg->stopping = 0; /* Create the instance network */ farg->instance = SNetNodeStreamCreate(node); farg->feedback = (*box_a)(farg->instance, info, location); farg->feedback = SNetRouteUpdate(info, farg->feedback, location); /* Feedback loop should end at this node. */ assert(STREAM_DEST(farg->feedback) == NULL); STREAM_DEST(farg->feedback) = node; /* Create two self-referencing streams. */ farg->selfref2 = SNetNodeStreamCreate(node); STREAM_DEST(farg->selfref2) = node; farg->selfref4 = SNetNodeStreamCreate(node); STREAM_DEST(farg->selfref4) = node; farg->entity = SNetEntityCreate( ENTITY_fbdisp, location, locvec, "<feedback>", NULL, (void*)farg); } else { SNetExprListDestroy( guards); SNetVariantListDestroy(back_patterns); output = input; } SNetLocvecFeedbackLeave(locvec); SNetDetSwapLevel(detlevel); return output; }
/** * Convenience function for creating * Star, DetStar, StarIncarnate or DetStarIncarnate, * dependent on parameters is_incarnate and is_det. */ static snet_stream_t *CreateStar( snet_stream_t *input, snet_info_t *info, int location, snet_variant_list_t *exit_patterns, snet_expr_list_t *guards, snet_startup_fun_t box_a, snet_startup_fun_t box_b, bool is_incarnate, bool is_det) { snet_stream_t *output; node_t *node; star_arg_t *sarg; snet_locvec_t *locvec; locvec = SNetLocvecGet(info); if (!is_incarnate) { SNetLocvecStarEnter(locvec); } else { assert(false); } output = SNetStreamCreate(0); node = SNetNodeNew(NODE_star, location, &input, 1, &output, 1, SNetNodeStar, SNetStopStar, SNetTermStar); sarg = NODE_SPEC(node, star); sarg->input = input; sarg->collector = output; sarg->exit_patterns = exit_patterns; sarg->guards = guards; sarg->is_incarnate = is_incarnate; sarg->is_det = is_det; sarg->is_detsup = (SNetDetGetLevel() > 0); sarg->stopping = 0; /* create operand A */ sarg->instance = SNetNodeStreamCreate(node); (void) SNetLocvecStarSpawn(locvec); SNetSubnetIncrLevel(); sarg->internal = (*box_a)(sarg->instance, info, location); SNetSubnetDecrLevel(); (void) SNetLocvecStarSpawnRet(locvec); /* direct destination of operand back to this node */ STREAM_DEST(sarg->internal) = node; /* Is this a Star followed by only a Sync? */ if (SNetZipperEnabled() && NODE_TYPE(STREAM_DEST(sarg->instance)) == NODE_sync && STREAM_FROM(sarg->internal) == STREAM_DEST(sarg->instance)) { /* Replace the combination of star + sync with a fused sync-star. */ sync_arg_t *sync = NODE_SPEC(STREAM_DEST(sarg->instance), sync); /* if (SNetVerbose()) { printf("Replacing a star + sync with a fused sync-star.\n"); } */ output = SNetZipper(input, info, location, exit_patterns, guards, sync->patterns, sync->guard_exprs); SNetEntityDestroy(sync->entity); SNetVariantDestroy(sync->merged_pattern); SNetDelete(STREAM_DEST(sarg->instance)); SNetStreamDestroy(sarg->instance); SNetStreamDestroy(sarg->internal); SNetStreamDestroy(sarg->collector); SNetMemFree(node); } else { sarg->entity = SNetEntityCreate( ENTITY_star, location, locvec, "<star>", NULL, (void *) sarg); if (!is_incarnate) { /* the "top-level" star also creates a collector */ output = SNetCollectorDynamic(sarg->collector, location, info, is_det, node); SNetNodeTableAdd(sarg->internal); } } if (!is_incarnate) { SNetLocvecStarLeave(locvec); } return output; }