Beispiel #1
0
/**
 * Peeks the top record of all streams in waitingset,
 * if there is a terminate record, the stream is closed
 * and removed from the waitingset
 */
static int DestroyTermInWaitingSet(snet_stream_iter_t *wait_iter,
    snet_streamset_t *waitingset)
{
  int destroy_cnt=0;
  if ( !SNetStreamsetIsEmpty( waitingset)) {
    SNetStreamIterReset( wait_iter, waitingset);
    while( SNetStreamIterHasNext( wait_iter)) {
      snet_stream_desc_t *sd = SNetStreamIterNext( wait_iter);
      snet_record_t *wait_rec = SNetStreamPeek( sd);

      /* for this stream, check if there is a termination record next */
      if ( wait_rec != NULL &&
          SNetRecGetDescriptor( wait_rec) == REC_terminate ) {
        /* consume, remove from waiting set and free the stream */
        (void) SNetStreamRead( sd);
        SNetStreamIterRemove( wait_iter);
        SNetStreamClose( sd, true);
        /* update destroyed counter */
        destroy_cnt++;
        /* destroy record */
        SNetRecDestroy( wait_rec);
      }
      /* else do nothing */
    }
  }
  return destroy_cnt;
}
Beispiel #2
0
static void FbCollReadFbi(struct fbcoll_state *state)
{
  snet_record_t *rec;

  assert( false == state->terminate );

  /* read from feedback stream */
  rec = SNetStreamRead( state->backstream);

  switch( SNetRecGetDescriptor( rec)) {

    case REC_data:
      /* relay data record */
      SNetStreamWrite( state->outstream, rec);
      /* mode switch to FB0 (there is a next iteration) */
      state->mode = FBCOLL_FB0;
      break;

    case REC_sort_end:
      assert( 0 == SNetRecGetLevel(rec) );
      switch(state->mode) {
        case FBCOLL_FB0:
          state->mode = FBCOLL_FB1;
          /* increase counter (non-functional) */
          SNetRecSetNum( rec, SNetRecGetNum(rec)+1);
          SNetStreamWrite( state->outstream, rec);
          break;
        case FBCOLL_FB1:
          state->mode = FBCOLL_IN;
          /* kill the sort record */
          SNetRecDestroy( rec);
          break;
        default: assert(0);
      }
      break;

    case REC_sync:
      SNetStreamReplace( state->backstream, SNetRecGetStream( rec));
      SNetRecDestroy( rec);
      break;

    case REC_terminate:
    case REC_collect:
    default:
      assert(0);
      /* if ignoring, at least destroy ... */
      SNetRecDestroy( rec);
      break;
  }
}
Beispiel #3
0
/**
 * Get a record due to the collector setting
 */
static snet_record_t *GetRecord(
    snet_streamset_t *readyset,
    int incount,
    snet_stream_desc_t **cur_stream)
{
  assert(incount >= 1 && *readyset != NULL);
  if (*cur_stream == NULL || SNetStreamPeek(*cur_stream) == NULL) {
    if (incount == 1) {
      *cur_stream = *readyset;
    } else {
      *cur_stream = SNetStreamPoll(readyset);
    }
  }
  return SNetStreamRead(*cur_stream);
}
Beispiel #4
0
/* helper functions to handle mode the feedback collector is in */
static void FbCollReadIn(struct fbcoll_state *state)
{
  snet_record_t *rec;

  assert( false == state->terminate );

  /* read from input stream */
  rec = SNetStreamRead( state->instream);

  switch( SNetRecGetDescriptor( rec)) {

    case REC_data:
      /* relay data record */
      SNetStreamWrite( state->outstream, rec);
      /* append a sort record */
      SNetStreamWrite(
          state->outstream,
          SNetRecCreate( REC_sort_end, 0, 1 ) /*type, lvl, num*/
          );
      /* mode switch to FB1 */
      state->mode = FBCOLL_FB1;
      break;

    case REC_sort_end:
      /* increase the level and forward */
      SNetRecSetLevel( rec, SNetRecGetLevel(rec)+1);
      SNetStreamWrite( state->outstream, rec);
      break;

    case REC_terminate:
      state->terminate = true;
      SNetStreamWrite( state->outstream, rec);
      /* note that no sort record has to be appended */
      break;

    case REC_sync:
      SNetStreamReplace( state->instream, SNetRecGetStream( rec));
      SNetRecDestroy( rec);
      break;

    case REC_collect:
    default:
      assert(0);
      /* if ignoring, at least destroy ... */
      SNetRecDestroy( rec);
      break;
  }
}
Beispiel #5
0
static void FeedbackBufTask(snet_entity_t *, void *arg)
{
  fbbuf_arg_t *fbbarg = (fbbuf_arg_t *)arg;

  snet_stream_desc_t *instream;
  snet_stream_desc_t *outstream;
  snet_record_t *rec;
  int out_counter = 0;
  int out_capacity;

  instream   = SNetStreamOpen(fbbarg->in,  'r');
  outstream  = SNetStreamOpen(fbbarg->out, 'w');
  out_capacity =  fbbarg->out_capacity;
  SNetMemFree( fbbarg);


  /* MAIN LOOP */
  while(1) {

    rec = SNetStreamRead(instream);
    if( SNetRecGetDescriptor(rec) == REC_terminate ) {
      /* this means, the outstream does not exist anymore! */
      SNetRecDestroy(rec);
      break; /* exit main loop */
    }

    if (out_counter+1 >= out_capacity) {
      /* new stream */
      snet_stream_t *new_stream = SNetStreamCreate(out_capacity);
      SNetStreamWrite(outstream,
          SNetRecCreate(REC_sync, new_stream)
          );

      SNetStreamClose(outstream, false);
      outstream = SNetStreamOpen(new_stream, 'w');
      out_counter = 0;
    }
    /* write the record to the stream */
    SNetStreamWrite(outstream, rec);
    out_counter++;
  } /* END OF MAIN LOOP */

  SNetStreamClose(instream,  true);
  SNetStreamClose(outstream, false);
}
Beispiel #6
0
/**
 * Split box task.
 *
 * Implements both the non-deterministic and deterministic variants.
 */
static void SplitBoxTask(snet_entity_t *ent, void *arg)
{
  int i;
  split_arg_t *sarg = (split_arg_t *)arg;
  snet_stream_desc_t *initial, *instream;
  int ltag_val, utag_val;
  snet_info_t *info;
  snet_record_t *rec;
  snet_locvec_t *locvec;
  bool terminate = false;
  /* a list of all outstreams for all yet created instances */
  snet_streamset_t repos_set = NULL;
  snet_stream_iter_t *iter = SNetStreamIterCreate( &repos_set);
  /* a hashtable for fast lookup, initial capacity = 2^4 = 16 */
  hashtab_t *repos_tab = HashtabCreate( 4);
  (void) ent; /* NOT USED */

  /* for deterministic variant: */
  int counter = 0;

  initial = SNetStreamOpen(sarg->output, 'w');
  instream = SNetStreamOpen(sarg->input, 'r');

  /* MAIN LOOP START */
  while( !terminate) {
    /* read from input stream */
    rec = SNetStreamRead( instream);

    switch( SNetRecGetDescriptor( rec)) {

      case REC_data:
        /* get lower and upper tag values */
        ltag_val = SNetRecGetTag( rec, sarg->ltag);
        utag_val = SNetRecGetTag( rec, sarg->utag);

        /* for all tag values */
        for( i = ltag_val; i <= utag_val; i++) {
          snet_stream_desc_t *outstream = HashtabGet( repos_tab, i);

          if( outstream == NULL) {
            snet_stream_t *temp_stream;
            snet_stream_t *newstream_addr = SNetStreamCreate(0);
            /* instance does not exist yet, create it */
            outstream = SNetStreamOpen(newstream_addr, 'w');
            /* add to lookup table */
            HashtabPut( repos_tab, i, outstream);
            /* add to list */
            SNetStreamsetPut( &repos_set, outstream);

            /* create info and location vector for creation of this replica */
            info = SNetInfoCopy(sarg->info);
            locvec = SNetLocvecSplitSpawn(SNetLocvecGet(sarg->info), i);
            SNetLocvecSet(info, locvec);

            if( sarg->is_byloc) {
              SNetRouteDynamicEnter(info, i, i, sarg->boxfun);
              temp_stream = sarg->boxfun(newstream_addr, info, i);
              temp_stream = SNetRouteUpdate(info, temp_stream, sarg->location);
              SNetRouteDynamicExit(info, i, i, sarg->boxfun);
            } else {
              SNetRouteDynamicEnter(info, i, sarg->location, sarg->boxfun);
              temp_stream = sarg->boxfun(newstream_addr, info, sarg->location);
              temp_stream = SNetRouteUpdate(info, temp_stream, sarg->location);
              SNetRouteDynamicExit(info, i, sarg->location, sarg->boxfun);
            }

            /* destroy info and location vector */
            SNetLocvecDestroy(locvec);
            SNetInfoDestroy(info);

            if(temp_stream != NULL) {
              /* notify collector about the new instance via initial */
              SNetStreamWrite( initial,
                  SNetRecCreate( REC_collect, temp_stream));
            }
          } /* end if (outstream==NULL) */

          /* multicast the record */
          SNetStreamWrite( outstream,
              /* copy record for all but the last tag value */
              (i!=utag_val) ? SNetRecCopy( rec) : rec
              );
        } /* end for all tags  ltag_val <= i <= utag_val */

        /* If deterministic, append a sort record to *all* registered
         * instances and the initial stream.
         */
        if( sarg->is_det ) {
          /* reset iterator */
          SNetStreamIterReset( iter, &repos_set);
          while( SNetStreamIterHasNext( iter)) {
            snet_stream_desc_t *cur_stream = SNetStreamIterNext( iter);

            SNetStreamWrite( cur_stream,
                SNetRecCreate( REC_sort_end, 0, counter));
          }
          /* Now also send a sort record to initial,
             after the collect records for new instances have been sent */
          SNetStreamWrite( initial,
              SNetRecCreate( REC_sort_end, 0, counter));
        }
        /* increment counter for deterministic variant */
        counter += 1;
        break;

      case REC_sync:
        {
          snet_stream_t *newstream = SNetRecGetStream( rec);
          SNetStreamReplace( instream, newstream);
          SNetRecDestroy( rec);
        }
        break;

      case REC_sort_end:
        /* broadcast the sort record */
        SNetStreamIterReset( iter, &repos_set);
        /* all instances receive copies of the record */
        while( SNetStreamIterHasNext( iter)) {
          snet_stream_desc_t *cur_stream = SNetStreamIterNext( iter);
          SNetStreamWrite( cur_stream,
              SNetRecCreate( REC_sort_end,
                /* we have to increase level */
                SNetRecGetLevel( rec)+1,
                SNetRecGetNum( rec))
              );
        }
        /* send the original record to the initial stream,
           but with increased level */
        SNetRecSetLevel( rec, SNetRecGetLevel( rec) + 1);
        SNetStreamWrite( initial, rec);
        break;

      case REC_terminate:

        SNetStreamIterReset( iter, &repos_set);
        /* all instances receive copies of the record */
        while( SNetStreamIterHasNext( iter)) {
          snet_stream_desc_t *cur_stream = SNetStreamIterNext( iter);
          SNetStreamWrite( cur_stream, SNetRecCopy( rec));

          SNetStreamIterRemove( iter);
          /* close  the stream to the instance */
          SNetStreamClose( cur_stream, false);
        }
        /* send the original record to the initial stream */
        SNetStreamWrite( initial, rec);
        /* note that no sort record has to be appended */
        terminate = true;
        break;

      case REC_collect:
        /* invalid control record */
      default:
        assert( 0);
        /* if ignore, at least destroy it */
        SNetRecDestroy( rec);
    }
  } /* MAIN LOOP END */

  /* destroy repository */
  HashtabDestroy( repos_tab);
  SNetStreamIterDestroy( iter);

  /* close and destroy initial stream */
  SNetStreamClose( initial, false);
  /* close instream */
  SNetStreamClose( instream, true);

  SNetLocvecDestroy(SNetLocvecGet(sarg->info));
  SNetInfoDestroy(sarg->info);
  /* destroy the argument */
  SNetMemFree( sarg);
} /* END of SPLIT BOX TASK */
Beispiel #7
0
/**
 * Star component task
 */
static void StarBoxTask(void *arg)
{
  star_arg_t *sarg = arg;
  snet_record_t *rec;

  /* read from input stream */
  rec = SNetStreamRead( sarg->instream);

  switch( SNetRecGetDescriptor( rec)) {

    case REC_data:
      if( MatchesExitPattern( rec, sarg->exit_patterns, sarg->guards)) {
        assert(!sarg->sync_cleanup);
#ifdef DEBUG_PRINT_GC
        SNetUtilDebugNoticeEnt( ent,
            "[STAR] Notice: Data leaves replication network.");
#endif
        /* send rec to collector */
        SNetStreamWrite( sarg->outstream, rec);
      } else {
        /* if instance has not been created yet, create it */
        if( sarg->nextstream == NULL) {
          CreateOperandNetwork(&sarg->nextstream, sarg, sarg->outstream);
        }
        /* send the record to the instance */
        SNetStreamWrite( sarg->nextstream, rec);
      } /* end if not matches exit pattern */

      /* deterministic non-incarnate has to append control records */
      if (sarg->is_det && !sarg->is_incarnate) {
        /* send new sort record to collector level=0, counter=0*/
        SNetStreamWrite( sarg->outstream,
            SNetRecCreate( REC_sort_end, 0, sarg->counter) );

        /* if has next instance, send new sort record */
        if (sarg->nextstream != NULL) {
          SNetStreamWrite( sarg->nextstream,
              SNetRecCreate( REC_sort_end, 0, sarg->counter) );
        }
        /* increment counter */
        sarg->counter++;

      }
#ifdef ENABLE_GC
      else if (sarg->sync_cleanup) {
        snet_record_t *term_rec;
        /*
         * If sync_cleanup is set, we decided to postpone termination
         * due to garbage collection triggered by a sync record until now.
         * Postponing was done in order not to create the operand network unnecessarily
         * only to be able to forward the sync record.
         */
        assert( sarg->nextstream != NULL);
        /* first send a sync record to the next instance */
        SNetStreamWrite( sarg->nextstream,
            SNetRecCreate( REC_sync, SNetStreamGet(sarg->instream)) );


        /* send a terminate record to collector, it will close and
           destroy the stream */
        term_rec = SNetRecCreate(REC_terminate);
        SNetRecSetFlag(term_rec);
        SNetStreamWrite( sarg->outstream, term_rec);

#ifdef DEBUG_PRINT_GC
        /* terminating due to GC */
        SNetUtilDebugNoticeEnt( ent,
            "[STAR] Notice: Destroying star dispatcher due to GC, "
            "delayed until new data record!"
            );
#endif
        SNetStreamClose(sarg->nextstream, false);
        SNetStreamClose(sarg->instream, false);
        TerminateStarBoxTask(sarg->outstream,sarg);
        return;
      }
#endif /* ENABLE_GC */
      break;

    case REC_sync:
      {
        snet_stream_t *newstream = SNetRecGetStream( rec);
#ifdef ENABLE_GC
        snet_locvec_t *loc = SNetStreamGetSource( newstream);
#ifdef DEBUG_PRINT_GC
        if (loc != NULL) {
          int size = SNetLocvecPrintSize(loc) + 1;
          char srecloc[size];
          srecloc[size - 1] = '\0';
          SNetLocvecPrint(srecloc, loc);
          SNetUtilDebugNoticeTask(
                "[STAR] Notice: Received sync record with a stream with source %s.",
                srecloc
                );
        }
#endif
        /* TODO
         * It is not necessary to carry the whole location vector in the
         * next stream of a star-entity, only a flag. As a prerequisite,
         * non_incarnates must not clean themselves up!
         */
        /*
         * Only incarnates are eligible for cleanup!
         * check if the source (location) of the stream and the own location are
         * (subsequent) star dispatcher entities of the same star combinator network
         * -> if so, we can clean-up ourselves
         */
        if ( sarg->is_incarnate && loc != NULL ) {
          assert( true == SNetLocvecEqualParent(loc, SNetLocvecGet(sarg->info)) );
          /* If the next instance is already created, we can forward the sync-record
           * immediately and terminate.
           * Otherwise we postpone termination to the point when a next data record
           * is received, as we create the operand network then.
           */
          if (sarg->nextstream != NULL) {
            snet_record_t *term_rec;
            /* forward the sync record  */
            SNetStreamWrite( sarg->nextstream, rec);
            /* send a terminate record to collector, it will close and
               destroy the stream */
            term_rec = SNetRecCreate(REC_terminate);
            SNetRecSetFlag(term_rec);
            SNetStreamWrite( sarg->outstream, term_rec);

#ifdef DEBUG_PRINT_GC
            /* terminating due to GC */
            SNetUtilDebugNoticeEnt( ent,
                "[STAR] Notice: Destroying star dispatcher due to GC, "
                "immediately on sync!"
                );
#endif
            SNetStreamClose(sarg->nextstream, false);
            SNetStreamClose(sarg->instream, true);
            TerminateStarBoxTask(sarg->outstream,sarg);
            return;
          } else {
            sarg->sync_cleanup = true;
#ifdef DEBUG_PRINT_GC
            SNetUtilDebugNoticeEnt( ent,
                "[STAR] Notice: Remembering delayed destruction.");
#endif
            /* handle sync record as usual */
            SNetStreamReplace( sarg->instream, newstream);
            SNetRecDestroy( rec);
          }
        } else
#endif /* ENABLE_GC */
        {
          /* handle sync record as usual */
          SNetStreamReplace( sarg->instream, newstream);
          SNetRecDestroy( rec);
        }
      }
      break;


    case REC_sort_end:
      {
        int rec_lvl = SNetRecGetLevel(rec);
        /* send a copy to the box, if exists */
        if( sarg->nextstream != NULL) {
          SNetStreamWrite(
              sarg->nextstream,
              SNetRecCreate( REC_sort_end,
                (!sarg->is_incarnate)? rec_lvl+1 : rec_lvl,
                SNetRecGetNum(rec) )
              );
        }

        /* send the original one to the collector */
        if (!sarg->is_incarnate) {
          /* if non-incarnate, we have to increase level */
          SNetRecSetLevel( rec, rec_lvl+1);
        }
        SNetStreamWrite( sarg->outstream, rec);
      }
      break;

    case REC_terminate:
      if( sarg->nextstream != NULL) {
        SNetStreamWrite( sarg->nextstream, SNetRecCopy( rec));
        SNetStreamClose( sarg->nextstream, false);
      }
      SNetStreamWrite( sarg->outstream, rec);
      /* note that no sort record has to be appended */
      SNetStreamClose(sarg->instream, true);
      TerminateStarBoxTask(sarg->outstream,sarg);

      return;

    case REC_collect:
    default:
      SNetUtilDebugFatal("Unknown record type!");
      /* if ignore, at least destroy ... */
      SNetRecDestroy( rec);
  }
  SNetThreadingRespawn(NULL);
}
Beispiel #8
0
static void BoxTask(snet_entity_t *ent, void *arg)
{
#ifdef DBG_RT_TRACE_BOX_TIMINGS
  static struct timeval tv_in;
  static struct timeval tv_out;
#endif

#ifdef SNET_DEBUG_COUNTERS
  snet_time_t time_in;
  snet_time_t time_out;
  long mseconds;
#endif /* SNET_DEBUG_COUNTERS */

  box_arg_t *barg = (box_arg_t *)arg;
  snet_record_t *rec;
  snet_stream_desc_t *instream, *outstream;
  bool terminate = false;

  instream = SNetStreamOpen(barg->input, 'r');
  outstream =  SNetStreamOpen(barg->output, 'w');
  /* set out descriptor */
  barg->hnd.out_sd = outstream;
  /* set entity */
  barg->hnd.ent = ent;

  /* MAIN LOOP */
  while(!terminate) {
    /* read from input stream */
    rec = SNetStreamRead(instream);

    switch(SNetRecGetDescriptor(rec)) {
      case REC_trigger_initialiser:
      case REC_data:
      	barg->hnd.rec = rec;

#ifdef DBG_RT_TRACE_BOX_TIMINGS
        gettimeofday(&tv_in, NULL);
        SNetUtilDebugNoticeEnt(ent,
            "[BOX] Firing box function at %lf.",
            tv_in.tv_sec + tv_in.tv_usec / 1000000.0
            );
#endif
#ifdef SNET_DEBUG_COUNTERS
        SNetDebugTimeGetTime(&time_in);
#endif /* SNET_DEBUG_COUNTERS */

#ifdef USE_USER_EVENT_LOGGING
        /* Emit a monitoring message of a record read to be processed by a box */
        if (SNetRecGetDescriptor(rec) == REC_data) {
          SNetThreadingEventSignal(ent,
              SNetMonInfoCreate(EV_MESSAGE_IN, MON_RECORD, rec)
              );
        }
#endif

        /* execute box function and update execution realm */
        barg->hnd = *barg->boxfun(&barg->hnd);
        barg->hnd = *barg->exerealm_update(&barg->hnd);

        /*
         * Emit an event here?
         * SNetMonInfoEvent(EV_BOX_???, MON_RECORD, rec);
         */

#ifdef DBG_RT_TRACE_BOX_TIMINGS
        gettimeofday(&tv_out, NULL);
        SNetUtilDebugNoticeEnt(ent,
            "[BOX] Return from box function after %lf sec.",
            (tv_out.tv_sec - tv_in.tv_sec) + (tv_out.tv_usec - tv_in.tv_usec) / 1000000.0
            );
#endif


#ifdef SNET_DEBUG_COUNTERS
        SNetDebugTimeGetTime(&time_out);
        mseconds = SNetDebugTimeDifferenceInMilliseconds(&time_in, &time_out);
        SNetDebugCountersIncreaseCounter(mseconds, SNET_COUNTER_TIME_BOX);
#endif /* SNET_DEBUG_COUNTERS */

        SNetRecDestroy(rec);

        /* restrict to one data record per execution */
        //SNetThreadingYield();

        /* check the box task should be migrated after one record execution */
        SNetThreadingCheckMigrate();
        break;

      case REC_sync:
        {
          snet_stream_t *newstream = SNetRecGetStream(rec);
          SNetStreamReplace(instream, newstream);
          SNetRecDestroy(rec);
        }
        break;

      case REC_sort_end:
        /* forward the sort record */
        SNetStreamWrite(outstream, rec);
        break;

      case REC_terminate:
      	barg->hnd = *barg->exerealm_destroy(&barg->hnd);
        SNetStreamWrite(outstream, rec);
        terminate = true;
        break;

      case REC_collect:
      default:
        assert(0);
    }
  } /* MAIN LOOP END */
  barg->hnd = *barg->exerealm_destroy(&barg->hnd);
  SNetStreamClose(instream, true);
  SNetStreamClose(outstream, false);
 
  /* destroy box arg */
  SNetVariantListDestroy(barg->hnd.vars);
  SNetIntListListDestroy(barg->hnd.sign);
  SNetMemFree( barg);
}
Beispiel #9
0
/**
 * The feedback buffer, in the back-loop
 */
static void FeedbackBufTask(snet_entity_t *ent, void *arg)
{
  fbbuf_arg_t *fbbarg = (fbbuf_arg_t *)arg;

  snet_stream_desc_t *instream;
  snet_stream_desc_t *outstream;
  snet_queue_t *internal_buffer;
  snet_record_t *rec;
  int out_capacity;
  int max_read;
  (void) ent; /* NOT USED */

  instream   = SNetStreamOpen(fbbarg->in,  'r');
  outstream  = SNetStreamOpen(fbbarg->out, 'w');
  out_capacity =  fbbarg->out_capacity;
  SNetMemFree( fbbarg);

  internal_buffer = SNetQueueCreate();
  max_read = out_capacity; /* TODO better usual stream capacity */

  /* MAIN LOOP */
  while(1) {
    int n = 0;
    rec = NULL;

    /* STEP 1: read n=min(available,max_read) records from input stream */

    /* read first record of the actual dispatch */
    if (0 == SNetQueueSize(internal_buffer)) {
      rec = SNetStreamRead(instream);
      /* only in empty mode! */
      if( REC_terminate == SNetRecGetDescriptor( rec)) {
        /* this means, the outstream does not exist anymore! */
        SNetRecDestroy(rec);
        goto feedback_buf_epilogue;
      }
    } else {
      SNetThreadingYield();
      if ( SNetStreamPeek(instream) != NULL ) {
        rec = SNetStreamRead(instream);
        assert( REC_terminate != SNetRecGetDescriptor( rec) );
      }
    }

    if (rec != NULL) {
      n = 1;
      /* put record into internal buffer */
      (void) SNetQueuePut(internal_buffer, rec);
    }


    while ( n<=max_read && SNetStreamPeek(instream)!=NULL ) {
      rec = SNetStreamRead(instream);

      /* check if we will need a larger outstream, and if so,
       * create a larger stream
       */
      if (SNetQueueSize(internal_buffer)+1 >= out_capacity) {
        snet_stream_t *new_stream;
        out_capacity *= 2;

        new_stream = SNetStreamCreate(out_capacity);
        (void) SNetQueuePut(internal_buffer, SNetRecCreate(REC_sync, new_stream));
      }

      /* put record into internal buffer */
      (void) SNetQueuePut(internal_buffer, rec);
      n++;
    }

    /* STEP 2: try to empty the internal buffer */
    rec = SNetQueuePeek(internal_buffer);

    while (rec != NULL) {
      snet_stream_t *new_stream = NULL;
      if( REC_sync == SNetRecGetDescriptor( rec)) {
        new_stream = SNetRecGetStream(rec);
      }
      if (0 == SNetStreamTryWrite(outstream, rec)) {
        snet_record_t *rem;
        /* success, also remove from queue */
        rem = SNetQueueGet(internal_buffer);
        assert( rem == rec );

        if (new_stream != NULL) {
          /* written sync record, now change stream */
          SNetStreamClose(outstream, false);
          outstream = SNetStreamOpen(new_stream, 'w');
        }
      } else {
        /* there remain elements in the buffer */
        break;
      }
      /* for the next iteration */
      rec = SNetQueuePeek(internal_buffer);
    }
  } /* END OF MAIN LOOP */

feedback_buf_epilogue:

  SNetQueueDestroy(internal_buffer);

  SNetStreamClose(instream,   true);
  SNetStreamClose(outstream,  false);
}
Beispiel #10
0
/**
 * The feedback dispatcher, at the end of the
 * feedback combinator loop
 */
static void FeedbackDispTask(snet_entity_t *ent, void *arg)
{
  fbdisp_arg_t *fbdarg = (fbdisp_arg_t *)arg;

  snet_stream_desc_t *instream;
  snet_stream_desc_t *outstream;
  snet_stream_desc_t *backstream;
  bool terminate = false;
  snet_record_t *rec;
  (void) ent; /* NOT USED */

  instream   = SNetStreamOpen(fbdarg->in,  'r');
  outstream  = SNetStreamOpen(fbdarg->out, 'w');
  backstream = SNetStreamOpen(fbdarg->fbo, 'w');

  /* MAIN LOOP */
  while( !terminate) {

    /* read from input stream */
    rec = SNetStreamRead( instream);

    switch( SNetRecGetDescriptor( rec)) {

      case REC_data:
        /* route data record */
        if( MatchesBackPattern( rec, fbdarg->back_patterns, fbdarg->guards)) {
          /* send rec back into the loop */
          SNetStreamWrite( backstream, rec);
        } else {
          /* send to output */
          SNetStreamWrite( outstream, rec);
        }
        break;

      case REC_sort_end:
        {
          int lvl = SNetRecGetLevel(rec);
          if ( 0 == lvl ) {
            SNetStreamWrite( backstream, rec);
          } else {
            assert( lvl > 0 );
            SNetRecSetLevel( rec, lvl-1);
            SNetStreamWrite( outstream, rec);
          }
        }
        break;

      case REC_terminate:
        terminate = true;
#ifndef FEEDBACK_OMIT_BUFFER
        /* a terminate record is sent in the backloop for the buffer */
        SNetStreamWrite( backstream, SNetRecCopy( rec));
#endif
        SNetStreamWrite( outstream, rec);
        break;

      case REC_sync:
        SNetStreamReplace( instream, SNetRecGetStream( rec));
        SNetRecDestroy( rec);
        break;

      case REC_collect:
      default:
        assert(0);
        /* if ignoring, at least destroy ... */
        SNetRecDestroy( rec);
        break;
    }

  } /* END OF MAIN LOOP */

  SNetStreamClose(instream,   true);
  SNetStreamClose(outstream,  false);
  SNetStreamClose(backstream, false);

  SNetVariantListDestroy( fbdarg->back_patterns);
  SNetExprListDestroy( fbdarg->guards);
  SNetMemFree( fbdarg);
}