void Step:: finishTask(Step::ptr step, int taskid, pBuffer result) { Interval result_interval; if (result) result_interval = result->getInterval (); TASKINFO TaskInfo ti(format("Step::finishTask %2% on %1%") % step.raw ()->operation_name() % result_interval); if (result) { // Result must have the same number of channels and sample rate as previous cache. // Call deprecateCache(Interval::Interval_ALL) to erase the cache when chainging number of channels or sample rate. step.raw ()->cache_->put (result); } auto self = step.write (); int matched_task = self->running_tasks.count (taskid); if (1 != matched_task) { Log("C = %d, taskid = %x on %s") % matched_task % taskid % self->operation_name (); EXCEPTION_ASSERT_EQUALS( 1, matched_task ); } Intervals expected_output = self->running_tasks[ taskid ]; Intervals update_miss = expected_output - result_interval; self->not_started_ |= update_miss; if (!result) { TASKINFO TaskInfo(format("The task was cancelled. Restoring %1% for %2%") % update_miss % self->operation_name()); } else { if (update_miss) { TaskInfo(format("These samples were supposed to be updated by the task but missed: %1% by %2%") % update_miss % self->operation_name()); } if (result_interval - expected_output) { // These samples were not supposed to be updated by the task but were calculated anyway TaskInfo(format("Unexpected extras: %1% = (%2%) - (%3%) from %4%") % (result_interval - expected_output) % result_interval % expected_output % self->operation_name()); // The samples are still marked as invalid. Would need to remove the // extra calculated samples from not_started_ but that would fail // in a situation where deprecatedCache is called after the task has // been created. So not_started_ can't be modified here (unless calls // to deprecatedCache were tracked). } } self->running_tasks.erase ( taskid ); self.unlock (); step.raw ()->wait_for_tasks_.notify_all (); }
void Step:: test() { // It should keep a cache for a signal processing step (defined by an OpertionDesc). // // The cache description should contain information about what's out_of_date // and what's currently being updated. { // Create an OperationDesc pBuffer b(new Buffer(Interval(60,70), 40, 7)); for (unsigned c=0; c<b->number_of_channels (); ++c) { float *p = b->getChannel (c)->waveform_data ()->getCpuMemory (); for (int i=0; i<b->number_of_samples (); ++i) p[i] = c + 1+i/(float)b->number_of_samples (); } // Create a Step Step::ptr s2( new Step(OperationDesc::ptr())); shared_state<Step>::weak_ptr ws = s2; Step::ptr s = ws.lock (); // It should contain information about what's out_of_date and what's currently being updated. int taskid = s->registerTask(b->getInterval ()); EXCEPTION_ASSERT_EQUALS(s->not_started (), ~Intervals(b->getInterval ())); EXCEPTION_ASSERT_EQUALS(s->out_of_date(), Intervals::Intervals_ALL); Step::finishTask(s, taskid, b); EXCEPTION_ASSERT_EQUALS(s->out_of_date(), ~Intervals(b->getInterval ())); EXCEPTION_ASSERT( *b == *Step::readFixedLengthFromCache (s, b->getInterval ()) ); } // A crashed signal processing step should behave as a transparent operation. { OperationDesc::ptr silence(new Signal::OperationSetSilent(Signal::Interval(2,3))); Step s(silence); EXCEPTION_ASSERT(!s.get_crashed ()); EXCEPTION_ASSERT(s.operation_desc ()); EXCEPTION_ASSERT(s.operation_desc ().read ()->createOperation (0)); EXCEPTION_ASSERT(!dynamic_cast<Test::TransparentOperationDesc*>(s.operation_desc ().raw ())); EXCEPTION_ASSERT(!dynamic_cast<Test::TransparentOperation*>(s.operation_desc ().read ()->createOperation (0).get ())); s.mark_as_crashed_and_get_invalidator (); EXCEPTION_ASSERT(s.get_crashed ()); EXCEPTION_ASSERT(s.operation_desc ()); EXCEPTION_ASSERT(s.operation_desc ().read ()->createOperation (0)); EXCEPTION_ASSERT(dynamic_cast<Test::TransparentOperationDesc*>(s.operation_desc ().raw ())); EXCEPTION_ASSERT(dynamic_cast<Test::TransparentOperation*>(s.operation_desc ().read ()->createOperation (0).get ())); } }
void GraphInvalidator:: deprecateCache(const Dag& dag, Step::ptr step, Signal::Intervals what) { // Invalidate the source first what = step.write ()->deprecateCache(what); // Invalidate the targets afterwards // Otherwise the scheduler might start working on data that isn't ready yet for (Step::ptr ts: dag.targetSteps(step)) deprecateCache(dag, ts, what); }