c4snet_data_t *C4SNetShallowCopy(c4snet_data_t *data) { #if HAVE_SYNC_ATOMIC_BUILTINS /* Temporary fix for race condition: */ AAF(&data->ref_count, 1); #else /* Old code, which contains a race condition: */ data->ref_count++; #endif return data; }
/* Scan other workers for stealable items */ static bool SNetWorkerSteal(worker_t *thief) { int i; assert(thief->loot.desc == NULL); assert(thief->loot.item == NULL); for (i = 0; i < snet_worker_count && !thief->loot.desc; ++i) { thief->victim_id = 1 + (thief->victim_id % snet_worker_count); if (thief->victim_id != thief->id) { worker_t *victim = snet_workers[thief->victim_id]; if (victim && trylock_worker(victim, thief)) { AAF(&victim->steal_turn->turn, 1); SNetWorkerStealVictim(victim, thief); AAF(&victim->steal_turn->turn, 1); unlock_worker(victim, thief); } } } return (thief->loot.desc != NULL); }
/* Merge a stream to an identity landing with the subsequent stream. */ static snet_stream_desc_t *SNetMergeStreams(snet_stream_desc_t **desc_ptr) { snet_stream_desc_t *desc = *desc_ptr; snet_stream_desc_t *next = DESC_LAND_SPEC(desc, identity)->outdesc; fifo_node_t *fifo_tail_start; fifo_node_t *fifo_tail_end; fifo_node_t *node; int count = 0; /* Remove all data from the queue towards the garbage landing. */ fifo_tail_start = SNetFifoGetTail(&desc->fifo, &fifo_tail_end); /* Count the number of data items in the captured list. */ for (node = fifo_tail_start; node; node = node->next) { ++count; } /* Append the captured list onto the subsequent stream. */ SNetFifoPutTail(&next->fifo, fifo_tail_start, fifo_tail_end); /* Reconnect the source landing of the next landing. */ next->source = desc->source; /* Increase the reference count by the number of added records. */ AAF(&(next->refs), count); /* Report statistics. */ if (SNetDebug()) { printf("%s: collecting %d recs, %d drefs, %d nrefs\n", __func__, count, desc->refs, next->refs); } /* Convert the identity landing into garbage. */ SNetBecomeGarbage(desc->landing); /* Make sure no one ever attempts to write to the dissolved stream. */ *desc_ptr = next; /* Unlock the garbage landing: some worker todo items may still need it. */ unlock_landing(desc->landing); /* Decrease reference count to the garbage collected stream. */ SNetDescDone(desc); /* Return the subsequent stream. */ return next; }
/* Process a stolen item. */ static void SNetWorkerLoot(worker_t *worker) { if (worker->loot.desc) { if (worker->loot.item) { if (worker->loot.count > 0) { AAF(&(worker->loot.item->count), worker->loot.count); } if (trylock_work_item(worker->loot.item, worker)) { if (worker->loot.item->count > 0) { SNetWorkerWorkItem(worker->loot.item, worker); } if (worker->loot.item->lock == worker->id) { unlock_work_item(worker->loot.item, worker); } } } else /* (worker->loot.item == NULL) */ { work_item_t *item = GetFreeWorkItem(worker); item->next_item = NULL; item->next_free = NULL; item->desc = worker->loot.desc; item->lock = worker->id; item->count = worker->loot.count; SNetHashPtrStore(worker->hash_ptab, item->desc, item); SNetWorkerWorkItem(item, worker); if (item->count == 0) { if (item->desc) { SNetHashPtrRemove(worker->hash_ptab, item->desc); } item->lock = worker->id; PutFreeWorkItem(worker, item); } else { item->lock = 0; item->next_item = worker->prev->next_item; BAR(); worker->prev->next_item = worker->iter = item; } } worker->loot.desc = NULL; worker->loot.count = 0; worker->loot.item = NULL; worker->has_work = (worker->todo.head.next_item != NULL); } }
/* Add a new unit of work to the worker's todo list. * At return iterator should point to the new item. */ void SNetWorkerTodo(worker_t *worker, snet_stream_desc_t *desc) { work_item_t *item = SNetHashPtrLookup(worker->hash_ptab, desc); if (item) { /* Item may be locked by a thief. */ AAF(&item->count, 1); } else { item = GetFreeWorkItem(worker); item->count = 1; item->desc = desc; item->lock = 0; item->next_free = NULL; item->next_item = worker->prev->next_item; BAR(); worker->prev->next_item = item; worker->prev = item; SNetHashPtrStore(worker->hash_ptab, desc, item); worker->has_work = true; } }
AAF sin(const AAF & P) { if(P.is_infinite()) return AAF(interval(-1,1)); interval i = P.convert(); double w = i.width(); const double a = i.left(); const double b = i.right(); // y' = alpha*x+dzeta , the regression line // approximate y = sin(x) double alpha, dzeta, delta; if (w >= 2*PI ) { // the trivial case, the interval is larger than 2*PI // y' = 0 , delta = 1 cause -1 <= sin(x) <= +1 return AAF(interval(-1,1)); alpha = 0.0; dzeta = 0.0; delta = 1.0; } else { // case of the least squares double x[NPTS]; double y[NPTS]; double r[NPTS]; // residues, r[i] = y[i]-y'[i] x[0] = a; y[0] = sin(a); x[NPTS-1] = b; y[NPTS-1] = sin(b); double pas = w/(NPTS-1); for (unsigned i=1; i< NPTS-1; i++) { x[i] = x[i-1]+pas; y[i] = sin(x[i]); } // Calculation of xm and ym , averages of x and y double xm = 0; double ym = 0; for (unsigned i=0; i<NPTS; i++) { xm = xm + x[i]; ym = ym + y[i]; } xm = xm/NPTS; ym = ym/NPTS; // Calculation of alpha and dzeta double temp2 = 0; alpha = 0; for (unsigned i = 0; i < NPTS; i++) { const double temp1 = x[i] - xm; alpha += y[i]*temp1; temp2 += temp1*temp1; } alpha = alpha/temp2; // final alpha dzeta = ym - alpha*xm; // final dzeta // Calculation of the residues // We use the absolute value of the residues! for (unsigned i = 0; i < NPTS; i++) { r[i] = fabs(y[i] - (dzeta+alpha*x[i])); } // The error delta is the maximum // of the residues (in absolute values) delta = *std::max_element(r, r+NPTS); } return AAF(P, alpha, dzeta, delta, P.special); }
/* Work on an item. * * In case of a dissolved garbage stream update the source * stream of the work item. * * Return true iff a record was processed. * * If the contents of the item was merged with another item then * reset the item descriptor to NULL. */ static bool SNetWorkerWorkItem(work_item_t *const item, worker_t *worker) { work_item_t *lookup; /* Item must be owned and non-empty. */ assert(item->lock == worker->id); assert(item->count > 0); /* Claim destination landing. */ if (trylock_landing(item->desc->landing, worker) == false) { /* Nothing can be done. */ return false; } /* Bring item descriptors past any garbage collectable landings. */ while (item->desc->landing->type == LAND_garbage) { /* Get subsequent descriptor. */ snet_stream_desc_t *next_desc = DESC_LAND_SPEC(item->desc, siso)->outdesc; /* Release landing claim. */ unlock_landing(item->desc->landing); /* Decrease reference counts to descriptor. */ SNetDescRelease(item->desc, item->count); /* Take item out of hash table. */ SNetHashPtrRemove(worker->hash_ptab, item->desc); /* Update item descriptor. */ item->desc = next_desc; /* Also advance past subsequent garbage landings. */ while (next_desc->landing->type == LAND_garbage) { /* Get subsequent descriptor. */ item->desc = DESC_LAND_SPEC(next_desc, siso)->outdesc; /* Test if current descriptor is also in our hash table. */ lookup = (work_item_t *)SNetHashPtrLookup(worker->hash_ptab, next_desc); if (lookup && trylock_work_item(lookup, worker)) { /* Merge both descriptor counts into one. */ item->count += lookup->count; lookup->count = 0; unlock_work_item(lookup, worker); } /* Decrease reference counts to garbage descriptor. */ SNetDescRelease(next_desc, item->count); /* Advance to subsequent descriptor and repeat. */ next_desc = item->desc; } /* The new descriptor may already exist in hash table. */ lookup = (work_item_t *)SNetHashPtrLookup(worker->hash_ptab, next_desc); if (lookup) { /* Merge the two counts. */ AAF(&lookup->count, item->count); /* Reset item. */ item->count = 0; /* We already have this desciptor in lookup, so reset it. */ item->desc = NULL; /* We made progress. */ return true; } else /* (lookup == NULL) */ { /* Add new descriptor to hash table. */ SNetHashPtrStore(worker->hash_ptab, item->desc, item); /* Claim destination landing. */ if (trylock_landing(item->desc->landing, worker) == false) { /* We made progress anyway. */ return true; } } } /* Subtract one read license. */ --item->count; /* Unlock item so thieves can steal it while we work. */ unlock_work_item(item, worker); /* Finally, do the work by delegating to the streams layer. */ SNetStreamWork(item->desc, worker); /* We definitely made progress. */ return true; }