X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession.cc;h=378d4763bc6d02551a464719cba0dc7b1e384a1c;hb=1ae094813858a2b8cf5b08569edcb9b15d910729;hp=48f7fc30e9bec96b513fdb621977ed48289da8e5;hpb=c5619a0f981161b441da1216de1f9c2e26190768;p=ardour.git diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 48f7fc30e9..378d4763bc 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -256,6 +256,7 @@ Session::Session (AudioEngine &eng, _midi_port (default_midi_port), pending_events (2048), midi_requests (128), // the size of this should match the midi request pool size + diskstreams (new DiskstreamList), routes (new RouteList), auditioner ((Auditioner*) 0), _click_io ((IO*) 0), @@ -306,6 +307,7 @@ Session::Session (AudioEngine &eng, _midi_port (default_midi_port), pending_events (2048), midi_requests (16), + diskstreams (new DiskstreamList), routes (new RouteList), main_outs (0) @@ -439,18 +441,45 @@ Session::~Session () } #ifdef TRACK_DESTRUCTION - cerr << "delete diskstreams\n"; + cerr << "delete routes\n"; #endif /* TRACK_DESTRUCTION */ - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ) { - DiskstreamList::iterator tmp; - - tmp = i; - ++tmp; + { + RCUWriter writer (routes); + boost::shared_ptr r = writer.get_copy (); + for (RouteList::iterator i = r->begin(); i != r->end(); ) { + RouteList::iterator tmp; + tmp = i; + ++tmp; + cerr << "BEFORE: use count on route " << (*i)->name() << " = " << (*i).use_count() << endl; + (*i)->drop_references (); + cerr << "AFTER: use count on route " << (*i)->name() << " = " << (*i).use_count() << endl; + i = tmp; + } + r->clear (); + /* writer goes out of scope and updates master */ + } - delete *i; + routes.flush (); - i = tmp; - } +#ifdef TRACK_DESTRUCTION + cerr << "delete diskstreams\n"; +#endif /* TRACK_DESTRUCTION */ + { + RCUWriter dwriter (diskstreams); + boost::shared_ptr dsl = dwriter.get_copy(); + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ) { + DiskstreamList::iterator tmp; + + tmp = i; + ++tmp; + + (*i)->drop_references (); + + i = tmp; + } + dsl->clear (); + } + diskstreams.flush (); #ifdef TRACK_DESTRUCTION cerr << "delete audio sources\n"; @@ -859,7 +888,7 @@ Session::playlist_length_changed (Playlist* pl) } void -Session::diskstream_playlist_changed (Diskstream* dstream) +Session::diskstream_playlist_changed (boost::shared_ptr dstream) { Playlist *playlist; @@ -933,13 +962,10 @@ Session::set_auto_input (bool yn) if (Config->get_use_hardware_monitoring() && transport_rolling()) { /* auto-input only makes a difference if we're rolling */ + + boost::shared_ptr dsl = diskstreams.reader(); - /* Even though this can called from RT context we are using - a non-tentative rwlock here, because the action must occur. - The rarity and short potential lock duration makes this "OK" - */ - Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (!auto_input); @@ -956,16 +982,19 @@ void Session::reset_input_monitor_state () { if (transport_rolling()) { - Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + + boost::shared_ptr dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input); } } } else { - Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + boost::shared_ptr dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (Config->get_use_hardware_monitoring()); @@ -1237,13 +1266,8 @@ Session::enable_record () send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe); if (Config->get_use_hardware_monitoring() && auto_input) { - /* Even though this can be called from RT context we are using - a non-tentative rwlock here, because the action must occur. - The rarity and short potential lock duration makes this "OK" - */ - Glib::RWLock::ReaderLock dsm (diskstream_lock); - - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + boost::shared_ptr dsl = diskstreams.reader(); + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->record_enabled ()) { (*i)->monitor_input (true); } @@ -1272,13 +1296,9 @@ Session::disable_record (bool rt_context, bool force) send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit); if (Config->get_use_hardware_monitoring() && auto_input) { - /* Even though this can be called from RT context we are using - a non-tentative rwlock here, because the action must occur. - The rarity and short potential lock duration makes this "OK" - */ - Glib::RWLock::ReaderLock dsm (diskstream_lock); + boost::shared_ptr dsl = diskstreams.reader(); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->record_enabled ()) { (*i)->monitor_input (false); } @@ -1299,13 +1319,9 @@ Session::step_back_from_record () g_atomic_int_set (&_record_status, Enabled); if (Config->get_use_hardware_monitoring()) { - /* Even though this can be called from RT context we are using - a non-tentative rwlock here, because the action must occur. - The rarity and short potential lock duration makes this "OK" - */ - Glib::RWLock::ReaderLock dsm (diskstream_lock); + boost::shared_ptr dsl = diskstreams.reader(); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if (auto_input && (*i)->record_enabled ()) { //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (false); @@ -1428,7 +1444,6 @@ Session::set_block_size (jack_nframes_t nframes) */ { - Glib::RWLock::ReaderLock dsm (diskstream_lock); vector::iterator i; uint32_t np; @@ -1475,7 +1490,8 @@ Session::set_block_size (jack_nframes_t nframes) (*i)->set_block_size (nframes); } - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + boost::shared_ptr dsl = diskstreams.reader(); + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { (*i)->set_block_size (nframes); } @@ -1863,7 +1879,7 @@ Session::new_audio_route (int input_channels, int output_channels) } void -Session::add_route (shared_ptr route) +Session::add_route (boost::shared_ptr route) { { RCUWriter writer (routes); @@ -1892,22 +1908,17 @@ Session::add_route (shared_ptr route) } void -Session::add_diskstream (Diskstream* dstream) +Session::add_diskstream (boost::shared_ptr dstream) { /* need to do this in case we're rolling at the time, to prevent false underruns */ dstream->do_refill_with_alloc(); { - Glib::RWLock::WriterLock lm (diskstream_lock); - diskstreams.push_back (dstream); + RCUWriter writer (diskstreams); + boost::shared_ptr ds = writer.get_copy(); + ds->push_back (dstream); } - /* take a reference to the diskstream, preventing it from - ever being deleted until the session itself goes away, - or chooses to remove it for its own purposes. - */ - - dstream->ref(); dstream->set_block_size (current_block_size); dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream)); @@ -1918,8 +1929,6 @@ Session::add_diskstream (Diskstream* dstream) set_dirty(); save_state (_current_snapshot_name); - - DiskstreamAdded (dstream); /* EMIT SIGNAL */ } void @@ -1958,20 +1967,19 @@ Session::remove_route (shared_ptr route) // FIXME: audio specific AudioTrack* at; - AudioDiskstream* ds = 0; + boost::shared_ptr ds; if ((at = dynamic_cast(route.get())) != 0) { - ds = &at->audio_diskstream(); + ds = at->audio_diskstream(); } if (ds) { { - Glib::RWLock::WriterLock lm (diskstream_lock); - diskstreams.remove (ds); + RCUWriter dsl (diskstreams); + boost::shared_ptr d = dsl.get_copy(); + d->remove (ds); } - - ds->unref (); } find_current_end (); @@ -1983,7 +1991,9 @@ Session::remove_route (shared_ptr route) save_state (_current_snapshot_name); - /* all shared ptrs to route should go out of scope here */ + /* try to cause everyone to drop their references */ + + route->drop_references (); } void @@ -2271,11 +2281,9 @@ Session::get_maximum_extent () const jack_nframes_t max = 0; jack_nframes_t me; - /* Don't take the diskstream lock. Caller must have other ways to - ensure atomicity. - */ + boost::shared_ptr dsl = diskstreams.reader(); - for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) { Playlist* pl = (*i)->playlist(); if ((me = pl->get_maximum_extent()) > max) { max = me; @@ -2285,32 +2293,32 @@ Session::get_maximum_extent () const return max; } -Diskstream * +boost::shared_ptr Session::diskstream_by_name (string name) { - Glib::RWLock::ReaderLock lm (diskstream_lock); + boost::shared_ptr dsl = diskstreams.reader(); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->name() == name) { - return* i; + return *i; } } - return 0; + return boost::shared_ptr((Diskstream*) 0); } -Diskstream * +boost::shared_ptr Session::diskstream_by_id (const PBD::ID& id) { - Glib::RWLock::ReaderLock lm (diskstream_lock); + boost::shared_ptr dsl = diskstreams.reader(); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->id() == id) { return *i; } } - return 0; + return boost::shared_ptr((Diskstream*) 0); } /* AudioRegion management */ @@ -2621,10 +2629,10 @@ int Session::remove_last_capture () { list r; - - Glib::RWLock::ReaderLock lm (diskstream_lock); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + boost::shared_ptr dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { list& l = (*i)->last_capture_regions(); if (!l.empty()) { @@ -3185,10 +3193,11 @@ Session::set_all_mute (bool yn) uint32_t Session::n_diskstreams () const { - Glib::RWLock::ReaderLock lm (diskstream_lock); uint32_t n = 0; - for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + boost::shared_ptr dsl = diskstreams.reader(); + + for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) { if (!(*i)->hidden()) { n++; } @@ -3207,15 +3216,15 @@ Session::graph_reordered () return; } - Glib::RWLock::ReaderLock lm2 (diskstream_lock); - resort_routes (); /* force all diskstreams to update their capture offset values to reflect any changes in latencies within the graph. */ - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + boost::shared_ptr dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { (*i)->set_capture_offset (); } } @@ -3494,11 +3503,9 @@ Session::remove_named_selection (NamedSelection* named_selection) void Session::reset_native_file_format () { - // jlc - WHY take routelock? - //RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__); - Glib::RWLock::ReaderLock lm2 (diskstream_lock); + boost::shared_ptr dsl = diskstreams.reader(); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { (*i)->reset_write_sources (false); } } @@ -3608,7 +3615,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf /* call tree *MUST* hold route_lock */ - if ((playlist = track.diskstream().playlist()) == 0) { + if ((playlist = track.diskstream()->playlist()) == 0) { goto out; } @@ -3618,7 +3625,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf goto out; } - nchans = track.audio_diskstream().n_channels(); + nchans = track.audio_diskstream()->n_channels(); dir = discover_best_sound_dir ();