Timeline: Fix thread synchronization issues during recording.

This commit is contained in:
Jonathan Moore Liles 2012-06-15 18:53:40 -07:00
parent ab8f23f15d
commit 1f9c2bbb6a
9 changed files with 66 additions and 17 deletions

View File

@ -36,6 +36,8 @@
// #include "const.h" // #include "const.h"
#include "debug.h" #include "debug.h"
#include "Mutex.H"
#include <algorithm> #include <algorithm>
using std::min; using std::min;
using std::max; using std::max;
@ -64,8 +66,11 @@ void *Loggable::_dirty_callback_arg = NULL;
static Mutex _lock;
Loggable::~Loggable ( ) Loggable::~Loggable ( )
{ {
Locker lock( _lock );;
_loggables[ _id ].loggable = NULL; _loggables[ _id ].loggable = NULL;
} }
@ -74,12 +79,15 @@ Loggable::~Loggable ( )
void void
Loggable::block_start ( void ) Loggable::block_start ( void )
{ {
Locker lock( _lock );;
++Loggable::_level; ++Loggable::_level;
} }
void void
Loggable::block_end ( void ) Loggable::block_end ( void )
{ {
Locker lock( _lock );;
--Loggable::_level; --Loggable::_level;
ASSERT( Loggable::_level >= 0, "Programming error" ); ASSERT( Loggable::_level >= 0, "Programming error" );
@ -559,6 +567,8 @@ Loggable::compact ( void )
void void
Loggable::log ( const char *fmt, ... ) Loggable::log ( const char *fmt, ... )
{ {
Locker lock( _lock );
static char * buf = NULL; static char * buf = NULL;
static size_t i = 0; static size_t i = 0;
static size_t buf_size = 0; static size_t buf_size = 0;
@ -689,6 +699,8 @@ Loggable::log_print( const Log_Entry *o, const Log_Entry *n ) const
void void
Loggable::log_start ( void ) Loggable::log_start ( void )
{ {
Locker lock( _lock );;
if ( ! _old_state ) if ( ! _old_state )
{ {
_old_state = new Log_Entry; _old_state = new Log_Entry;
@ -702,6 +714,8 @@ Loggable::log_start ( void )
void void
Loggable::log_end ( void ) Loggable::log_end ( void )
{ {
Locker lock( _lock );;
ASSERT( _old_state, "Programming error: log_end() called before log_start()" ); ASSERT( _old_state, "Programming error: log_end() called before log_start()" );
if ( --_nest > 0 ) if ( --_nest > 0 )
@ -737,6 +751,8 @@ Loggable::log_end ( void )
void void
Loggable::log_create ( void ) const Loggable::log_create ( void ) const
{ {
Locker lock( _lock );;
set_dirty(); set_dirty();
if ( ! _fp ) if ( ! _fp )
@ -786,6 +802,8 @@ Loggable::record_unjournaled ( void ) const
void void
Loggable::log_destroy ( void ) const Loggable::log_destroy ( void ) const
{ {
Locker lock( _lock );;
/* the unjournaled state may have changed: make a note of it. */ /* the unjournaled state may have changed: make a note of it. */
record_unjournaled(); record_unjournaled();

View File

@ -116,3 +116,10 @@ Thread::join ( void )
pthread_join( _thread, NULL ); pthread_join( _thread, NULL );
_thread = 0; _thread = 0;
} }
void
Thread::exit ( void *retval )
{
pthread_exit( retval );
_thread = 0;
}

View File

@ -52,5 +52,6 @@ public:
bool clone ( void *(*entry_point)(void *), void *arg ); bool clone ( void *(*entry_point)(void *), void *arg );
void detach ( void ); void detach ( void );
void join ( void ); void join ( void );
void exit ( void *retval = 0 );
}; };

View File

@ -175,11 +175,14 @@ Audio_Region::read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channe
return cnt; return cnt;
} }
/** prepare for capturing */ /** prepare for capturing */
void void
Audio_Region::prepare ( void ) Audio_Region::prepare ( void )
{ {
THREAD_ASSERT( Capture );
DMESSAGE( "Preparing capture region" );
log_start(); log_start();
} }
@ -218,15 +221,10 @@ Audio_Region::finalize ( nframes_t frame )
_range.length = frame - _range.start; _range.length = frame - _range.start;
log_end();
_clip->close(); _clip->close();
_clip->open(); _clip->open();
Fl::lock(); log_end();
redraw();
Fl::awake();
Fl::unlock();
return true; return true;
} }

View File

@ -30,6 +30,7 @@ class Audio_Sequence;
#include "const.h" #include "const.h"
#include "debug.h" #include "debug.h"
#include <unistd.h>
@ -139,14 +140,24 @@ Disk_Stream::detach ( void )
/** stop the IO thread. */ /** stop the IO thread. */
void void
Disk_Stream::shutdown ( void ) Disk_Stream::shutdown ( void )
{
if ( _thread.running() )
{ {
_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 */
while ( _terminate )
{
usleep( 100 );
block_processed(); block_processed();
}
if ( _thread.running() )
_thread.join(); _thread.join();
sem_destroy( &_blocks );
sem_init( &_blocks, 0, 0 );
}
} }
Track * Track *

View File

@ -94,11 +94,12 @@ protected:
virtual void flush ( void ) = 0; virtual void flush ( void ) = 0;
void run ( void ); void run ( void );
void shutdown ( void );
void detach ( void ); void detach ( void );
public: public:
void shutdown ( void );
/* must be set before any Disk_Streams are created */ /* must be set before any Disk_Streams are created */
static float seconds_to_buffer; static float seconds_to_buffer;
static size_t disk_io_kbytes; static size_t disk_io_kbytes;

View File

@ -74,10 +74,10 @@ Record_DS::disk_thread ( void )
{ {
_thread.name( "Capture" ); _thread.name( "Capture" );
track()->record( _capture, _frame );
DMESSAGE( "capture thread running..." ); DMESSAGE( "capture thread running..." );
track()->record( _capture, _frame );
const nframes_t nframes = _nframes * _disk_io_blocks; const nframes_t nframes = _nframes * _disk_io_blocks;
/* buffer to hold the interleaved data returned by the track reader */ /* buffer to hold the interleaved data returned by the track reader */
@ -211,7 +211,10 @@ Record_DS::disk_thread ( void )
delete c; delete c;
_terminate = false; _terminate = false;
DMESSAGE( "capture thread gone" ); DMESSAGE( "capture thread gone" );
_thread.exit();
} }
@ -258,7 +261,7 @@ Record_DS::stop ( nframes_t frame )
_stop_frame = frame; _stop_frame = frame;
detach(); // detach();
DMESSAGE( "recording finished" ); DMESSAGE( "recording finished" );
} }

View File

@ -75,6 +75,17 @@ Timeline::stop ( void )
t->record_ds->stop( frame ); t->record_ds->stop( frame );
} }
/* wait until finalization is complete before continuing */
DMESSAGE( "Waiting for record threads to shutdown" );
for ( int i = tracks->children(); i-- ; )
{
Track *t = (Track*)tracks->child( i );
if ( t->armed() && t->record_ds )
t->record_ds->shutdown();
}
Loggable::block_end(); Loggable::block_end();
activate(); activate();

View File

@ -304,7 +304,6 @@ Track::finalize ( Capture *c, nframes_t frame )
* them */ * them */
c->audio_file->finalize(); c->audio_file->finalize();
/* peaks get finalized here */
c->region->finalize( frame ); c->region->finalize( frame );
nframes_t capture_offset = 0; nframes_t capture_offset = 0;