WorkerCrashLogger:: WorkerCrashLogger(Workers::ptr workers, bool consume_exceptions) : workers_(workers), consume_exceptions_(consume_exceptions) { EXCEPTION_ASSERTX(dynamic_cast<Signal::QtEventWorker::QtEventWorkerFactory*>(workers->workerfactory ()), "WorkerCrashLogger only supports QtEventWorkers"); moveToThread (&thread_); // Remove responsibility for event processing for this when the the thread finishes connect(&thread_, SIGNAL(finished()), SLOT(finished())); thread_.start (); auto ww = workers.write (); // Log any future worker crashes connect(dynamic_cast<Signal::QtEventWorker::QtEventWorkerFactory*>(ww->workerfactory ()), SIGNAL(worker_quit(std::exception_ptr,Signal::ComputingEngine::ptr)), SLOT(worker_quit(std::exception_ptr,Signal::ComputingEngine::ptr))); // Log previous worker crashes. As the new thread owns this, 'check' will // be executed in the new thread. if (consume_exceptions) QTimer::singleShot (0, this, SLOT(check_all_previously_crashed_and_consume())); else QTimer::singleShot (0, this, SLOT(check_all_previously_crashed_without_consuming())); }
ExportAudioDialog::ExportAudioDialog( Sawe::Project* project, SelectionModel* selection_model, RenderView* render_view ) : QDialog(project->mainWindow()), ui(new Ui::ExportAudioDialog), project(project), selection_model(selection_model), render_view(render_view), total(0), drawnFinished_(false) { EXCEPTION_ASSERTX(false, "not implemented: exportTarget"); TaskInfo ti("ExportAudioDialog"); ui->setupUi(this); update_timer.setSingleShot( true ); update_timer.setInterval( 100 ); connect( &update_timer, SIGNAL( timeout() ), SLOT( callUpdate() ) ); setupGui(); }
void setup_signal_survivor(int sig) { struct sigaction sa; sa.sa_flags = SA_SIGINFO; sigemptyset (&sa.sa_mask); sa.__sigaction_u.__sa_sigaction = &seghandle; bool sigsegv_handler = sigaction(sig, &sa, NULL) != -1; EXCEPTION_ASSERTX(sigsegv_handler, "failed to setup SIGSEGV handler"); }
void ExportAudioDialog:: start(Signal::pOperation filter) { filemame = QFileDialog::getSaveFileName(project->mainWindow(), "Export audio", "", "Wav audio (*.wav)"); if (0 == filemame.length()) { // User pressed cancel return; } QString extension = ".wav"; if (filemame.length() < extension.length()) filemame += extension; if (0 != QString::compare(filemame.mid(filemame.length() - extension.length()), extension, Qt::CaseInsensitive)) filemame += extension; EXCEPTION_ASSERTX(false, "Use Signal::Processing namespace"); /* exportTarget.reset(new Signal::Target(&project->layers, "File export (" + filemame.toStdString() + ")" , false, true)); Signal::PostSink* postsink = exportTarget->post_sink(); postsink->filter( filter ); std::vector<Signal::pOperation> sinks; sinks.push_back( Signal::pOperation( new Adapters::WriteWav( filemame.toStdString() )) ); postsink->sinks(sinks); postsink->isUnderfedIfInvalid = true; Signal::Intervals expected_data; if (filter) expected_data = ~filter->zeroed_samples_recursive(); else expected_data = Signal::Intervals::Intervals_ALL; expected_data &= Signal::Interval(0, project->worker.source()->number_of_samples()); postsink->invalidate_samples( expected_data ); total = expected_data.count(); bool isFinished = false; ui->buttonBoxAbort->setEnabled( !isFinished ); ui->buttonBoxOk->setEnabled( isFinished ); float L = total/postsink->sample_rate(); ui->labelExporting->setText(QString("Exporting signal of length %1").arg( Signal::SourceBase::lengthLongFormat(L).c_str())); if (filter) setWindowTitle("Exporting selection"); else setWindowTitle("Exporting entire signal"); hide(); setWindowModality( Qt::WindowModal ); show(); */ }
void ExportAudioDialog:: populateTodoList() { EXCEPTION_ASSERTX(false, "Use Signal::Processing namespace"); /* if (project->worker.todo_list() || !exportTarget) return; project->worker.center = 0; project->worker.target(exportTarget); */ }
void DrawWaveform:: draw_glList( boost::shared_ptr<RenderData> chunk, void (*renderFunction)( boost::shared_ptr<RenderData> ), bool force_redraw ) { #ifdef LEGACY_OPENGL // do a cache lookup std::map<void*, ListCounter>::iterator itr = _chunkGlList.find(chunk.get()); if (_chunkGlList.end() == itr && force_redraw) { force_redraw = false; } // cache miss or force_redraw if (_chunkGlList.end() == itr || force_redraw) { ListCounter cnt; if (force_redraw) { cnt = itr->second; cnt.age = ListCounter::Age_InUse; } else { cnt.age = ListCounter::Age_JustCreated; cnt.displayList = glGenLists(1); } if (0 != cnt.displayList) { glNewList(cnt.displayList, GL_COMPILE_AND_EXECUTE ); renderFunction( chunk ); glEndList(); _chunkGlList[chunk.get()] = cnt; } else { // render anyway, but not into display list and enqueue gc _enqueueGcDisplayList = true; renderFunction( chunk ); } } else { // render cache itr->second.age = ListCounter::Age_InUse; // don't remove glCallList( itr->second.displayList ); } #else EXCEPTION_ASSERTX(false, "requires LEGACY_OPENGL"); #endif }
QtEventWorker:: QtEventWorker (Signal::ComputingEngine::ptr computing_engine, Signal::Processing::ISchedule::ptr schedule, bool wakeuprightaway) : computing_engine_(computing_engine), schedule_(schedule), thread_(new QTerminatableThread), exception_(new std::exception_ptr()), ltf_wakeups_("qteventworker wakeups"), ltf_tasks_("qteventworker tasks"), active_time_since_start_(0) { EXCEPTION_ASSERTX(QThread::currentThread ()->eventDispatcher (), "Worker uses a QThread with an event loop. The QEventLoop requires QApplication"); qRegisterMetaType<std::exception_ptr>("std::exception_ptr"); qRegisterMetaType<Signal::ComputingEngine::ptr>("Signal::ComputingEngine::ptr"); // Create terminated_exception_ try { // To make caught_exception() non-zero if the thread is terminated even // though no exact information about the crash reason is stored. The // log file might contain more details. BOOST_THROW_EXCEPTION(QtEventWorker::TerminatedException()); } catch (...) { terminated_exception_ = std::current_exception (); } // Start the worker thread as an event based background thread thread_->setParent (this); thread_->setObjectName (QString("Worker %1").arg (computing_engine ? vartype(*computing_engine).c_str () : "(null)")); thread_->start (QThread::IdlePriority); moveToThread (thread_); connect (thread_, SIGNAL(finished()), SLOT(finished())); if (wakeuprightaway) { // Initial check to see if work can begin right away wakeup (); // will be dispatched to execute in thread_ } }
void PlaybackMarkersController:: receiveNextMarker() { PlaybackMarkersModel::Markers::iterator itr = model()->currentMarker(); PlaybackMarkersModel::Markers::iterator next_itr = itr; next_itr++; float pos; if (next_itr != model()->markers().end()) { model()->setCurrentMaker( next_itr ); pos = *next_itr; } else { EXCEPTION_ASSERTX(false, "Use Signal::Processing namespace"); pos = 0.f; // pos = render_view_->model->project()->worker.length(); } render_view_->setPosition( Heightmap::Position( pos, render_view_->model->_qz) ); render_view_->redraw(); }
virtual Task getTask(Signal::ComputingEngine::ptr) const override { EXCEPTION_ASSERTX(false, "testing that worker catches exceptions from a scheduler"); // unreachable code return Task(); }
void BlockUpdater:: processUpdates(bool isMainThread) { if (!isMainThread) { /** * MergerTexture needs to prepare the block when it is about to be rendered. * Which is a tad late and requires a new FBO and then a swap back to the main FBO. * * Then after a glFlush the update thread can write to the block, but not before * the glFlush as the merged texture might not be ready. updater_->processUpdates * should check this and put the update on hold until showNewTexture has been called, * indicating that a new frame has begun an thus that there has been a glFlush since * MergerTexture. */ EXCEPTION_ASSERTX(false, "Painting on blocks from the update thread is not implemented"); } list<pair<pBlock, DrawFunc>> q; queue_->swap(q); if (q.empty ()) return; GlGroupMarker gpm("ProcessUpdates"); if (!fbo2block_) fbo2block_.reset (new Fbo2Block); // draw multiple updates to a block together map<pBlock, list<DrawFunc>> p; for (auto i = q.begin (); i != q.end (); i++) p[i->first].push_back(move(i->second)); // release resources bound in function objects q_success_.clear (); list<pair<pBlock, DrawFunc>> q_failed; map<Heightmap::pBlock,GlTexture::ptr> textures; for (auto i = p.begin (); i != p.end (); i++) { const pBlock& block = i->first; glProjection M; if (isMainThread) textures[block] = block->sourceTexture (); else textures[block] = Heightmap::Render::BlockTextures::get1 (); auto fbo_mapping = fbo2block_->begin (block->getOverlappingRegion (), block->sourceTexture (), textures[block], M); for (auto j = i->second.begin (); j != i->second.end (); j++) { DrawFunc& draw = *j; // try again next frame with draw calls that return false (i.e if a sync object isn'r ready yet) // keep successfull draw calls around to prevent opengl resources from being reused (causing sync or corrupted data) before opengl is done with them (draw(M) ? q_success_ : q_failed) .push_back (pair<pBlock, DrawFunc>(block,move(*j))); } fbo_mapping.release (); } for (const auto& v : textures) v.first->setTexture(v.second); // reinsert failed draw attempts auto w = queue_.write (); w->swap (q_failed); // if any new updates arrived during processing push any failed draw attempts to the back of the queue for (auto& a : q_failed) w->push_back (std::move(a)); }
Signal::OperationDesc::ptr MicrophoneRecorderDesc:: copy() const { EXCEPTION_ASSERTX(false, "Can't make a copy of microphone recording"); return Signal::OperationDesc::ptr(); }
Signal::Interval DrawnWaveform:: affectedInterval( const Signal::Interval& ) const { EXCEPTION_ASSERTX(false, "Not implemented"); return Signal::Interval(); }
void Bedroom:: test() { // It should allow different threads to sleep on this object until another thread calls wakeup() for (int j=0;j<2; j++) { Bedroom::ptr bedroom(new Bedroom); int snoozes = 10; SleepyFaceMock sleepyface1(bedroom, snoozes); SleepyFaceMock sleepyface2(bedroom, snoozes); sleepyface1.start (); sleepyface2.start (); for (int i=snoozes; i>=0; i--) { EXCEPTION_ASSERT_EQUALS(sleepyface1.wait (1), i>0?false:true); EXCEPTION_ASSERT_EQUALS(sleepyface2.wait (1), i>0?false:true); // sleepyface1 and sleepyface2 shoule be sleeping now EXCEPTION_ASSERT_EQUALS(bedroom->sleepers(), i>0?2:0); // they should have 'i' times left to snooze EXCEPTION_ASSERTX(sleepyface1.snooze () == i && sleepyface2.snooze () == i, (boost::format("sleepyface1=%d, sleepyface2=%d, i=%d") % sleepyface1.snooze () % sleepyface2.snooze () % i)); // should wake up both bedroom->wakeup(); } EXCEPTION_ASSERT(sleepyface1.isFinished ()); EXCEPTION_ASSERT(sleepyface2.isFinished ()); EXCEPTION_ASSERT_EQUALS(bedroom->sleepers(), 0); } // It should throw a BedroomClosed exception if someone tries to go to // sleep when the bedroom is closed. { Bedroom b; b.close (); EXPECT_EXCEPTION(BedroomClosed, b.getBed().sleep ()); } // It should just sleep until the given timeout has elapsed { Bedroom b; Timer t; bool woken_up_by_wakeup_call = b.getBed ().sleep (2); // The thread was sleeping in its bed for 2 ms. So the elapsed 'Timer' // time should be more than 2 ms but less than 3 ms. EXCEPTION_ASSERT_LESS(t.elapsed (), 3e-3); EXCEPTION_ASSERT_LESS(2e-3, t.elapsed ()); EXCEPTION_ASSERT(!woken_up_by_wakeup_call); // timeout } // It should just sleep until the given timeout has elapsed for (int i=0; i<40; i++) { //TaskTimer tt("It should just sleep until the given timeout has elapsed"); Bedroom::ptr bedroom(new Bedroom); SleepingBeautyMock sbm(bedroom, 1); EXCEPTION_ASSERT_EQUALS(0,bedroom->sleepers ()); sbm.start (); // wait for the thread to go to sleep and then timeout for (int j=0; j<100 && 0==sbm.timeoutCount (); j++) EXCEPTION_ASSERT( !sbm.wait (1) ); // wakeup bedroom->wakeup(); // the thread should finish soon EXCEPTION_ASSERT( sbm.wait (128) ); EXCEPTION_ASSERT_EQUALS(0,bedroom->sleepers ()); } // It should just sleep until the given timeout has elapsed for (int i=0; i<40; i++) { //TaskTimer tt("It should just sleep until the given timeout has elapsed"); Bedroom::ptr bedroom(new Bedroom); SleepingBeautyMock sbm(bedroom, 1000); EXCEPTION_ASSERT_EQUALS(0,bedroom->sleepers ()); sbm.start (); // wait for the thread to go to sleep for (int j=0; j<100 && 0==bedroom->sleepers (); j++) EXCEPTION_ASSERT( !sbm.wait (1) ); EXCEPTION_ASSERT_EQUALS(1,bedroom->sleepers ()); // wakeup bedroom->wakeup(); // the thread should finish soon EXCEPTION_ASSERT( sbm.wait (128) ); EXCEPTION_ASSERT_EQUALS(0,bedroom->sleepers ()); // with such a long timeout the number of timeouts should be 0 EXCEPTION_ASSERT_EQUALS(0,sbm.timeoutCount ()); } }