Exemplo n.º 1
0
/**
 * Collector task for dynamic combinators (star/split)
 * and the static parallel combinator
 */
void CollectorTask(snet_entity_t *ent, void *arg)
{
  coll_arg_t *carg = (coll_arg_t *)arg;
  snet_streamset_t readyset, waitingset;
  snet_stream_iter_t *wait_iter;
  snet_stream_desc_t *outstream;
  snet_stream_desc_t *curstream = NULL;
  snet_stream_desc_t *last = NULL;		// when the paired parallel terminate, it sends the sort_end record to the last branch
  snet_record_t *sort_rec = NULL;
  snet_record_t *term_rec = NULL;
  int incount;
  bool terminate = false;


  /* open outstream for writing */
  outstream = SNetStreamOpen(carg->output, 'w');

  readyset = waitingset = NULL;

  if (carg->is_static) {
    int i;
    incount = CARG_ST(carg, num);
    /* fill initial readyset of collector */
    for (i=0; i<incount; i++) {
      snet_stream_desc_t *tmp;
      /* open each stream in listening set for reading */
      tmp = SNetStreamOpen( CARG_ST(carg, inputs[i]), 'r');
      /* add each stream instreams[i] to listening set of collector */
      SNetStreamsetPut( &readyset, tmp);
    }
    SNetMemFree( CARG_ST(carg, inputs) );
  } else {
    incount = 1;
    /* Open initial stream and put into readyset */
    SNetStreamsetPut( &readyset,
        SNetStreamOpen(CARG_DYN(carg, input), 'r')
        );
  }

  /* create an iterator for waiting set, is reused within main loop*/
  wait_iter = SNetStreamIterCreate( &waitingset);

  /* MAIN LOOP */
  while( !terminate) {
    /* get a record */
    snet_record_t *rec = GetRecord(&readyset, incount, &curstream);
    /* process the record */
    switch( SNetRecGetDescriptor( rec)) {

      case REC_data:
        /* data record: forward to output */
        SNetStreamWrite( outstream, rec);
        break;

      case REC_sort_end:
      	/* curstream == last, this is the last branch and the paired parallel already terminates
      	 * increase the level by one because it was not increased by the paired parallel as it should be
      	 * Also later when last becomes the only waiting branch, the collector should terminate. However before terminating, it should pretend that parallel has sent the sort end from all branches
      	 */
      	if (curstream == last) {			// imply last != NULL, this will be the last branch and the paired parallel already terminates
      		SNetRecSetLevel(rec, SNetRecGetLevel(rec) + 1);			// increase the level by one because it was not increased by the paired parallel as it should be
      	}
      	if (last == NULL && SNetRecGetLevel(rec) == 0 && SNetRecGetNum(rec) == -1) {		// if last was not set, and collector receives a sort_end (l0, c-1) --> set the curstream as last
      		last = curstream;																															// from now on, any sort_end from last will be increased level by 1
      		SNetRecDestroy( rec);
      		break;			// ignore the sort_end
      	}

        ProcessSortRecord(ent, rec, &sort_rec, curstream, &readyset, &waitingset);
        /* end processing this stream */
        curstream = NULL;
        break;

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

      case REC_collect:
        /* only for dynamic collectors! */
        assert( false == carg->is_static );
        /* collect: add new stream to ready set */
#ifdef DESTROY_TERM_IN_WAITING_UPON_COLLECT
        /* but first, check if we can free resources by checking the
           waiting set for arrival of termination records */
        incount -= DestroyTermInWaitingSet(wait_iter, &waitingset);
        assert(incount > 0);
#endif
        /* finally, add new stream to ready set */
        SNetStreamsetPut(
            &readyset,
            SNetStreamOpen( SNetRecGetStream( rec), 'r')
            );
        /* update incoming counter */
        incount++;
        /* destroy collect record */
        SNetRecDestroy( rec);
        break;

      case REC_terminate:
        /* termination record: close stream and remove from ready set */
        ProcessTermRecord(rec, &term_rec, curstream, &readyset, &incount);
        /* stop processing this stream */
        curstream = NULL;
        break;

      default:
        assert(0);
        /* if ignore, at least destroy ... */
        SNetRecDestroy( rec);
    } /* end switch */

    /************* termination conditions *****************/
    if ( SNetStreamsetIsEmpty( &readyset)) {
      /* the streams which had a sort record are in the waitingset */
      if ( !SNetStreamsetIsEmpty( &waitingset)) {
        if ( carg->is_static && (1 == incount) ) {		// stat
          snet_stream_desc_t *in = (waitingset != NULL) ? waitingset : readyset;

          /* if last is the only one in the waitingset --> pretends that the already-terminated paired parallel has sent the sort end to all branches
           * Therefore restore the waitingset before terminating (so that a relevant sort_end is sent out) */
          if (in == last)
          	RestoreFromWaitingset(&waitingset, &readyset, &sort_rec, outstream);

          SNetStreamWrite( outstream,
              SNetRecCreate( REC_sync, SNetStreamGet(in))
              );
          SNetStreamClose( in, false);
          terminate = true;
#ifdef DEBUG_PRINT_GC
          /* terminating due to GC */
          SNetUtilDebugNoticeEnt( ent,
              "[COLL] Terminate static collector as only one branch left!"
              );
#endif
        } else
          RestoreFromWaitingset(&waitingset, &readyset, &sort_rec, outstream);
      } else {
        /* both ready set and waitingset are empty */
#ifdef DEBUG_PRINT_GC
        if (carg->is_static) {
          SNetUtilDebugNoticeEnt( ent,
              "[COLL] Terminate static collector as no inputs left!");
        }
#endif
        assert(term_rec != NULL);
        SNetStreamWrite( outstream, term_rec);
        term_rec = NULL;
        terminate = true;
      }
    }

     
    /************* end of termination conditions **********/
  } /* MAIN LOOP END */

  if (term_rec != NULL) {
    SNetRecDestroy(term_rec);
  }
  if (sort_rec != NULL) {
    SNetRecDestroy(sort_rec);
  }
  /* close outstream */
  SNetStreamClose( outstream, false);
  /* destroy iterator */
  SNetStreamIterDestroy( wait_iter);
  /* destroy argument */
  SNetMemFree( carg);
} /* END of DYNAMIC COLLECTOR TASK */
Exemplo n.º 2
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 */
Exemplo n.º 3
0
snet_stream_desc_t *SNetStreamPoll(snet_streamset_t *set)
{
  assert( *set != NULL);

  snet_stream_desc_t *result = NULL;
  /* get 'self', i.e. the task calling SNetStreamPoll()
   * the set is a simple pointer to the last element
   */
  snet_thread_t *self = SNetThreadingSelf();
  snet_stream_iter_t *iter;
  int cnt = 0;

  //self = (*set)->thr;

  iter = SNetStreamIterCreate(set);

  /* fast path: there is something anywhere */
  {
    while( SNetStreamIterHasNext(iter)) {
      snet_stream_desc_t *sd = SNetStreamIterNext( iter);
      snet_stream_t *s = sd->stream;
      pthread_mutex_lock(&s->lock);
      if (s->count > 0) result = sd;
      pthread_mutex_unlock(&s->lock);
    }
    if (result != NULL) {
      goto poll_fastpath;
    }
  }




  /* reset wakeup_sd */
  pthread_mutex_lock( &self->lock );
  self->wakeup_sd = NULL;
  pthread_mutex_unlock( &self->lock );

  /* for each stream in the set */
  SNetStreamIterReset(iter, set);
  while( SNetStreamIterHasNext(iter)) {
    snet_stream_desc_t *sd = SNetStreamIterNext( iter);
    snet_stream_t *s = sd->stream;

    /* lock stream (prod-side) */
    pthread_mutex_lock( &s->lock);
    { /* CS BEGIN */
      /* check if there is something in the buffer */
      if ( s->count > 0 ) {
        /* yes, we can stop iterating through streams. */
        pthread_mutex_lock( &self->lock );
        if (self->wakeup_sd == NULL) {
          self->wakeup_sd = sd;
        }
        /* unlock self */
        pthread_mutex_unlock( &self->lock );
        /* unlock stream */
        pthread_mutex_unlock( &s->lock);
        /* exit loop */
        break;

      } else {
        /* nothing in the buffer, register stream as activator */
        s->is_poll = 1;
        cnt++;
      }
    } /* CS END */
    /* unlock stream */
    pthread_mutex_unlock( &s->lock);
  } /* end for each stream */

  /* wait until wakeup_sd is set */
  pthread_mutex_lock( &self->lock );
  while( self->wakeup_sd == NULL ) {
    pthread_cond_wait(&self->pollcond, &self->lock);
  }
  result = self->wakeup_sd;
  self->wakeup_sd = NULL;
  pthread_mutex_unlock( &self->lock );

  SNetStreamIterReset(iter, set);
  while( SNetStreamIterHasNext(iter)) {
    snet_stream_t *s = (SNetStreamIterNext(iter))->stream;
    pthread_mutex_lock(&s->lock);
    s->is_poll = 0;
    pthread_mutex_unlock(&s->lock);
    if (--cnt == 0) break;
  }

poll_fastpath:
  SNetStreamIterDestroy(iter);
  /* 'rotate' list to stream descriptor for non-empty buffer */
  *set = result;

  return result;
}