Timeline: Lock ordering fixes.
This commit is contained in:
parent
0c5a46422a
commit
3756dea1d6
|
@ -146,10 +146,18 @@ Disk_Stream::shutdown ( void )
|
||||||
_terminate = true;
|
_terminate = true;
|
||||||
|
|
||||||
/* try to wake the thread so it'll see that it's time to die */
|
/* try to wake the thread so it'll see that it's time to die */
|
||||||
|
int total_ms = 0;
|
||||||
while ( _terminate )
|
while ( _terminate )
|
||||||
{
|
{
|
||||||
usleep( 100 );
|
usleep( 1000 * 10 );
|
||||||
|
total_ms += 10;
|
||||||
block_processed();
|
block_processed();
|
||||||
|
|
||||||
|
if ( total_ms > 100 )
|
||||||
|
{
|
||||||
|
WARNING("Disk_Stream thread has taken longer than %ims to respond to terminate signal.", total_ms );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_thread.join();
|
_thread.join();
|
||||||
|
|
|
@ -82,25 +82,22 @@ Playback_DS::read_block ( sample_t *buf, nframes_t nframes )
|
||||||
|
|
||||||
// printf( "IO: attempting to read block @ %lu\n", _frame );
|
// printf( "IO: attempting to read block @ %lu\n", _frame );
|
||||||
|
|
||||||
if ( ! sequence() )
|
|
||||||
{
|
|
||||||
/* FIXME: what to do here? */
|
|
||||||
// _frame += _nframes;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeline->rdlock();
|
timeline->rdlock();
|
||||||
|
|
||||||
/* FIXME: how does this work if _delay is not a multiple of bufsize? */
|
if ( sequence() )
|
||||||
|
|
||||||
if ( _frame >= _delay )
|
|
||||||
{
|
{
|
||||||
if ( ! sequence()->play( buf, _frame - _delay, nframes, channels() ) )
|
/* FIXME: how does this work if _delay is not a multiple of bufsize? */
|
||||||
WARNING( "Programming error?" );
|
|
||||||
|
if ( _frame >= _delay )
|
||||||
|
{
|
||||||
|
if ( ! sequence()->play( buf, _frame - _delay, nframes, channels() ) )
|
||||||
|
WARNING( "Programming error?" );
|
||||||
|
}
|
||||||
|
|
||||||
|
_frame += nframes;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_frame += nframes;
|
|
||||||
|
|
||||||
timeline->unlock();
|
timeline->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,13 +58,9 @@ Record_DS::write_block ( sample_t *buf, nframes_t nframes )
|
||||||
if ( ! ( timeline && sequence() ) )
|
if ( ! ( timeline && sequence() ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// timeline->wrlock();
|
|
||||||
|
|
||||||
track()->write( _capture, buf, nframes );
|
track()->write( _capture, buf, nframes );
|
||||||
|
|
||||||
_frames_written += nframes;
|
_frames_written += nframes;
|
||||||
|
|
||||||
// timeline->unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define AVOID_UNNECESSARY_COPYING 1
|
#define AVOID_UNNECESSARY_COPYING 1
|
||||||
|
|
|
@ -150,6 +150,10 @@ Timeline::stop ( void )
|
||||||
nframes_t
|
nframes_t
|
||||||
Timeline::process ( nframes_t nframes )
|
Timeline::process ( nframes_t nframes )
|
||||||
{
|
{
|
||||||
|
/* there is no need to acquire a readlock here because track *
|
||||||
|
addition/removal locks process() and track process() calls deal with
|
||||||
|
ringbuffers instead of reading the sequence data directly. */
|
||||||
|
|
||||||
for ( int i = tracks->children(); i-- ; )
|
for ( int i = tracks->children(); i-- ; )
|
||||||
{
|
{
|
||||||
Track *t = (Track*)tracks->child( i );
|
Track *t = (Track*)tracks->child( i );
|
||||||
|
|
|
@ -272,8 +272,14 @@ Track::record ( Capture *c, nframes_t frame )
|
||||||
/* open it again for reading in the GUI thread */
|
/* open it again for reading in the GUI thread */
|
||||||
// Audio_File *af = Audio_File::from_file( c->audio_file->name() );
|
// Audio_File *af = Audio_File::from_file( c->audio_file->name() );
|
||||||
|
|
||||||
|
/* must acquire a write lock because the Audio_Region constructor
|
||||||
|
* will add the region to the specified sequence */
|
||||||
|
timeline->wrlock();
|
||||||
|
|
||||||
c->region = new Audio_Region( c->audio_file, sequence(), frame );
|
c->region = new Audio_Region( c->audio_file, sequence(), frame );
|
||||||
|
|
||||||
|
timeline->unlock();
|
||||||
|
|
||||||
c->region->prepare();
|
c->region->prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,6 +304,8 @@ Track::finalize ( Capture *c, nframes_t frame )
|
||||||
/* adjust region start for latency */
|
/* adjust region start for latency */
|
||||||
/* FIXME: is just looking at the first channel good enough? */
|
/* FIXME: is just looking at the first channel good enough? */
|
||||||
|
|
||||||
|
timeline->wrlock();
|
||||||
|
|
||||||
DMESSAGE( "finalizing audio file" );
|
DMESSAGE( "finalizing audio file" );
|
||||||
/* must finalize audio before peaks file, otherwise another thread
|
/* must finalize audio before peaks file, otherwise another thread
|
||||||
* might think the peaks are out of date and attempt to regenerate
|
* might think the peaks are out of date and attempt to regenerate
|
||||||
|
@ -323,5 +331,7 @@ Track::finalize ( Capture *c, nframes_t frame )
|
||||||
|
|
||||||
c->region->offset( capture_offset );
|
c->region->offset( capture_offset );
|
||||||
|
|
||||||
|
timeline->unlock();
|
||||||
|
|
||||||
// delete c->audio_file;
|
// delete c->audio_file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,8 +154,12 @@ Sequence::overlaps ( Sequence_Widget *r )
|
||||||
void
|
void
|
||||||
Sequence::handle_widget_change ( nframes_t start, nframes_t length )
|
Sequence::handle_widget_change ( nframes_t start, nframes_t length )
|
||||||
{
|
{
|
||||||
|
/* this might be invoked from Capture or GUI thread */
|
||||||
|
Fl::lock();
|
||||||
sort();
|
sort();
|
||||||
timeline->damage_sequence();
|
timeline->damage_sequence();
|
||||||
|
Fl::unlock();
|
||||||
|
|
||||||
// timeline->update_length( start + length );
|
// timeline->update_length( start + length );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,8 +190,11 @@ Sequence::add ( Sequence_Widget *r )
|
||||||
|
|
||||||
if ( r->sequence() )
|
if ( r->sequence() )
|
||||||
{
|
{
|
||||||
|
/* This method can be called from the Capture thread as well as the GUI thread, so we must lock FLTK before redraw */
|
||||||
|
Fl::lock();
|
||||||
r->redraw();
|
r->redraw();
|
||||||
r->sequence()->remove( r );
|
r->sequence()->remove( r );
|
||||||
|
Fl::unlock();
|
||||||
// r->track()->redraw();
|
// r->track()->redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +211,7 @@ Sequence::remove ( Sequence_Widget *r )
|
||||||
_widgets.remove( r );
|
_widgets.remove( r );
|
||||||
|
|
||||||
handle_widget_change( r->start(), r->length() );
|
handle_widget_change( r->start(), r->length() );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static nframes_t
|
static nframes_t
|
||||||
|
|
|
@ -943,6 +943,10 @@ else if ( 0 == p )
|
||||||
progress_group->hide();
|
progress_group->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// never allow drawing timeline while loading, as this would cause lock recursion.
|
||||||
|
if ( timeline->visible() )
|
||||||
|
return;
|
||||||
|
|
||||||
static int oldp;
|
static int oldp;
|
||||||
static char pat[10];
|
static char pat[10];
|
||||||
|
|
||||||
|
|
|
@ -1253,6 +1253,8 @@ Timeline::draw ( void )
|
||||||
int bdx = 0;
|
int bdx = 0;
|
||||||
int bdw = 0;
|
int bdw = 0;
|
||||||
|
|
||||||
|
rdlock();
|
||||||
|
|
||||||
X = tracks->x() + bdx + 1;
|
X = tracks->x() + bdx + 1;
|
||||||
Y = tracks->y();
|
Y = tracks->y();
|
||||||
W = tracks->w() - bdw - 1;
|
W = tracks->w() - bdw - 1;
|
||||||
|
@ -1354,6 +1356,8 @@ done:
|
||||||
|
|
||||||
_old_xposition = xoffset;
|
_old_xposition = xoffset;
|
||||||
_old_yposition = panzoomer->y_value();
|
_old_yposition = panzoomer->y_value();
|
||||||
|
|
||||||
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -63,8 +63,8 @@ public:
|
||||||
void toggle_record ( void );
|
void toggle_record ( void );
|
||||||
int handle ( int m );
|
int handle ( int m );
|
||||||
|
|
||||||
bool rolling;
|
volatile bool rolling;
|
||||||
bool recording;
|
volatile bool recording;
|
||||||
|
|
||||||
void poll ( void );
|
void poll ( void );
|
||||||
void locate ( nframes_t frame );
|
void locate ( nframes_t frame );
|
||||||
|
|
|
@ -280,8 +280,9 @@ main ( int argc, char **argv )
|
||||||
if ( optind < argc )
|
if ( optind < argc )
|
||||||
{
|
{
|
||||||
MESSAGE( "Loading \"%s\"", argv[optind] );
|
MESSAGE( "Loading \"%s\"", argv[optind] );
|
||||||
|
Fl::lock();
|
||||||
tle->open( argv[optind] );
|
tle->open( argv[optind] );
|
||||||
|
Fl::unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue