From 1ae094813858a2b8cf5b08569edcb9b15d910729 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 16 Aug 2006 01:19:06 +0000 Subject: RCU-ification of AudioEngine port list, and DiskStreams. not well tested, but basically functional. better to get this in now rather than later. git-svn-id: svn://localhost/ardour2/trunk@828 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardour_ui.cc | 9 +- gtk2_ardour/ardour_ui.h | 2 - gtk2_ardour/ardour_ui_dialogs.cc | 4 - gtk2_ardour/audio_streamview.cc | 8 +- gtk2_ardour/audio_streamview.h | 2 +- gtk2_ardour/editor.cc | 8 +- gtk2_ardour/editor_audio_import.cc | 6 +- gtk2_ardour/editor_timefx.cc | 2 +- gtk2_ardour/playlist_selector.cc | 6 +- gtk2_ardour/plugin_selector.cc | 2 +- gtk2_ardour/route_time_axis.cc | 14 +-- gtk2_ardour/route_ui.cc | 10 +- gtk2_ardour/route_ui.h | 2 +- gtk2_ardour/streamview.cc | 8 +- gtk2_ardour/streamview.h | 4 +- libs/ardour/ardour/audio_diskstream.h | 7 +- libs/ardour/ardour/audio_track.h | 4 +- libs/ardour/ardour/audioengine.h | 5 +- libs/ardour/ardour/diskstream.h | 21 ++-- libs/ardour/ardour/route.h | 5 +- libs/ardour/ardour/session.h | 18 ++-- libs/ardour/ardour/track.h | 6 +- libs/ardour/audio_diskstream.cc | 4 - libs/ardour/audio_track.cc | 81 ++++++++------- libs/ardour/audioengine.cc | 92 +++++++++++++---- libs/ardour/auditioner.cc | 6 +- libs/ardour/diskstream.cc | 2 - libs/ardour/route.cc | 3 +- libs/ardour/session.cc | 181 ++++++++++++++++++---------------- libs/ardour/session_butler.cc | 18 ++-- libs/ardour/session_export.cc | 5 +- libs/ardour/session_process.cc | 37 +++---- libs/ardour/session_state.cc | 10 +- libs/ardour/session_transport.cc | 83 ++++++++-------- libs/ardour/track.cc | 5 - libs/pbd/pbd/rcu.h | 14 ++- 36 files changed, 354 insertions(+), 340 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index e5367d6280..bca27c7231 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -545,7 +545,7 @@ void ARDOUR_UI::count_recenabled_diskstreams (Route& route) { Track* track = dynamic_cast(&route); - if (track && track->diskstream().record_enabled()) { + if (track && track->diskstream()->record_enabled()) { rec_enabled_diskstreams++; } } @@ -917,11 +917,6 @@ restart JACK with more ports.")); } } -void -ARDOUR_UI::diskstream_added (Diskstream* ds) -{ -} - void ARDOUR_UI::do_transport_locate (jack_nframes_t new_position) { @@ -1172,7 +1167,7 @@ ARDOUR_UI::toggle_record_enable (uint32_t dstream) Track* t; if ((t = dynamic_cast(r.get())) != 0) { - t->diskstream().set_record_enabled (!t->diskstream().record_enabled()); + t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled()); } } if (session == 0) { diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 297c9c3c65..c8d0d70a7d 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -520,8 +520,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI sigc::connection point_one_second_connection; sigc::connection point_zero_one_second_connection; - void diskstream_added (ARDOUR::Diskstream*); - gint session_menu (GdkEventButton *); bool _will_create_new_session_automatically; diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 25f3068a81..c90480c1dd 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -76,10 +76,6 @@ ARDOUR_UI::connect_to_session (Session *s) rec_button.set_sensitive (true); shuttle_box.set_sensitive (true); - if (session->n_diskstreams() == 0) { - session->DiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added)); - } - if (connection_editor) { connection_editor->set_session (s); } diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index 82349947c6..d650df1563 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -225,7 +225,7 @@ AudioStreamView::playlist_modified () } void -AudioStreamView::playlist_changed (Diskstream *ds) +AudioStreamView::playlist_changed (boost::shared_ptr ds) { ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), ds)); @@ -399,7 +399,7 @@ AudioStreamView::setup_rec_box () peak_ready_connections.clear(); // FIXME - AudioDiskstream* ads = dynamic_cast(_trackview.get_diskstream()); + boost::shared_ptr ads = boost::dynamic_pointer_cast(_trackview.get_diskstream()); assert(ads); for (uint32_t n=0; n < ads->n_channels(); ++n) { @@ -431,8 +431,8 @@ AudioStreamView::setup_rec_box () AudioTrack* at; at = _trackview.audio_track(); /* we know what it is already */ - AudioDiskstream& ds = at->audio_diskstream(); - jack_nframes_t frame_pos = ds.current_capture_start (); + boost::shared_ptr ds = at->audio_diskstream(); + jack_nframes_t frame_pos = ds->current_capture_start (); gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos); gdouble xend; uint32_t fill_color; diff --git a/gtk2_ardour/audio_streamview.h b/gtk2_ardour/audio_streamview.h index 05ce8125f6..edda221bbd 100644 --- a/gtk2_ardour/audio_streamview.h +++ b/gtk2_ardour/audio_streamview.h @@ -87,7 +87,7 @@ class AudioStreamView : public StreamView void undisplay_diskstream (); void redisplay_diskstream (); void playlist_modified (); - void playlist_changed (ARDOUR::Diskstream *ds); + void playlist_changed (boost::shared_ptr); void add_crossfade (ARDOUR::Crossfade*); void remove_crossfade (ARDOUR::Crossfade*); diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 050ec6be90..2be8b2d73b 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1596,7 +1596,7 @@ Editor::build_track_region_context_menu (jack_nframes_t frame) AudioTimeAxisView* atv = dynamic_cast (clicked_trackview); if (atv) { - Diskstream* ds; + boost::shared_ptr ds; Playlist* pl; if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) { @@ -1623,7 +1623,7 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame) AudioTimeAxisView* atv = dynamic_cast (clicked_trackview); if (atv) { - Diskstream* ds; + boost::shared_ptr ds; Playlist* pl; AudioPlaylist* apl; @@ -3020,7 +3020,7 @@ Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32 Playlist* pl; vector results; RegionView* marv; - Diskstream* ds; + boost::shared_ptr ds; if ((ds = tv.get_diskstream()) == 0) { /* bus */ @@ -3246,7 +3246,7 @@ Editor::set_selected_regionview_from_region_list (Region& region, Selection::Ope Playlist* pl; vector results; RegionView* marv; - Diskstream* ds; + boost::shared_ptr ds; if ((ds = tatv->get_diskstream()) == 0) { /* bus */ diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index 8887135374..b6fdefa4d3 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -317,7 +317,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32 case ImportToTrack: if (track) { - Playlist* playlist = track->diskstream().playlist(); + Playlist* playlist = track->diskstream()->playlist(); AudioRegion* copy = new AudioRegion (region); begin_reversible_command (_("insert sndfile")); @@ -334,7 +334,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32 { boost::shared_ptr at (session->new_audio_track (in_chans, out_chans, Normal)); copy = new AudioRegion (region); - at->diskstream().playlist()->add_region (*copy, pos); + at->diskstream()->playlist()->add_region (*copy, pos); break; } @@ -342,7 +342,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32 { boost::shared_ptr at (session->new_audio_track (in_chans, out_chans, Destructive)); copy = new AudioRegion (region); - at->diskstream().playlist()->add_region (*copy, pos); + at->diskstream()->playlist()->add_region (*copy, pos); break; } } diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc index a3288ea8d0..caa9698b8c 100644 --- a/gtk2_ardour/editor_timefx.cc +++ b/gtk2_ardour/editor_timefx.cc @@ -188,7 +188,7 @@ Editor::do_timestretch (TimeStretchDialog& dialog) continue; } - if ((playlist = t->diskstream().playlist()) == 0) { + if ((playlist = t->diskstream()->playlist()) == 0) { i = tmp; continue; } diff --git a/gtk2_ardour/playlist_selector.cc b/gtk2_ardour/playlist_selector.cc index 8eaac7cb9d..68227d193c 100644 --- a/gtk2_ardour/playlist_selector.cc +++ b/gtk2_ardour/playlist_selector.cc @@ -90,7 +90,7 @@ void PlaylistSelector::show_for (RouteUI* ruix) { vector item; - Diskstream* this_ds; + boost::shared_ptr this_ds; string str; rui = ruix; @@ -116,7 +116,7 @@ PlaylistSelector::show_for (RouteUI* ruix) for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) { - Diskstream* ds = session->diskstream_by_id (x->first); + boost::shared_ptr ds = session->diskstream_by_id (x->first); if (ds == 0) { continue; @@ -243,7 +243,7 @@ PlaylistSelector::selection_changed () return; } - at->diskstream().use_playlist (apl); + at->diskstream()->use_playlist (apl); hide (); } diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc index 2ebaaae100..6c72767b11 100644 --- a/gtk2_ardour/plugin_selector.cc +++ b/gtk2_ardour/plugin_selector.cc @@ -226,7 +226,7 @@ PluginSelector::set_correct_focus() au_display.grab_focus(); return; } -#endif; +#endif } void diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index 05f832700e..e7a6df2f27 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -728,7 +728,7 @@ RouteTimeAxisView::rename_current_playlist () ArdourPrompter prompter (true); string name; - Diskstream *const ds = get_diskstream(); + boost::shared_ptr ds = get_diskstream(); if (!ds || ds->destructive()) return; @@ -759,7 +759,7 @@ RouteTimeAxisView::use_copy_playlist (bool prompt) { string name; - Diskstream *const ds = get_diskstream(); + boost::shared_ptr ds = get_diskstream(); if (!ds || ds->destructive()) return; @@ -800,7 +800,7 @@ RouteTimeAxisView::use_new_playlist (bool prompt) { string name; - Diskstream *const ds = get_diskstream(); + boost::shared_ptr ds = get_diskstream(); if (!ds || ds->destructive()) return; @@ -838,7 +838,7 @@ RouteTimeAxisView::use_new_playlist (bool prompt) void RouteTimeAxisView::clear_playlist () { - Diskstream *const ds = get_diskstream(); + boost::shared_ptr ds = get_diskstream(); if (!ds || ds->destructive()) return; @@ -963,7 +963,7 @@ RouteTimeAxisView::name() const Playlist * RouteTimeAxisView::playlist () const { - Diskstream *ds; + boost::shared_ptr ds; if ((ds = get_diskstream()) != 0) { return ds->playlist(); @@ -1013,7 +1013,7 @@ RouteTimeAxisView::hide_click () Region* RouteTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir) { - Diskstream *stream; + boost::shared_ptr stream; Playlist *playlist; if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) { @@ -1027,7 +1027,7 @@ bool RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op) { Playlist* what_we_got; - Diskstream* ds = get_diskstream(); + boost::shared_ptr ds = get_diskstream(); Playlist* playlist; bool ret = false; diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index 998385f66b..b2fdcaf7d4 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -74,7 +74,7 @@ RouteUI::RouteUI (boost::shared_ptr rt, ARDOUR::Session& sess, co if (is_track()) { boost::shared_ptr t = boost::dynamic_pointer_cast(_route); - t->diskstream().RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed)); + t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed)); _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed)); @@ -733,7 +733,7 @@ void RouteUI::route_removed () { ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::route_removed)); - + cerr << "Route UI @ " << this << " destroyed by impending end of route\n"; delete this; } @@ -905,15 +905,15 @@ RouteUI::audio_track() const return dynamic_cast(_route.get()); } -Diskstream* +boost::shared_ptr RouteUI::get_diskstream () const { boost::shared_ptr t; if ((t = boost::dynamic_pointer_cast(_route)) != 0) { - return &t->diskstream(); + return t->diskstream(); } else { - return 0; + return boost::shared_ptr ((Diskstream*) 0); } } diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h index 7415eddad6..8a257028e9 100644 --- a/gtk2_ardour/route_ui.h +++ b/gtk2_ardour/route_ui.h @@ -57,7 +57,7 @@ class RouteUI : public virtual AxisView ARDOUR::Track* track() const; ARDOUR::AudioTrack* audio_track() const; - ARDOUR::Diskstream* get_diskstream() const; + boost::shared_ptr get_diskstream() const; string name() const; diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index d1d163d7a2..733e27c4ab 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -206,7 +206,7 @@ StreamView::undisplay_diskstream () } void -StreamView::display_diskstream (Diskstream *ds) +StreamView::display_diskstream (boost::shared_ptr ds) { playlist_change_connection.disconnect(); playlist_changed (ds); @@ -224,7 +224,7 @@ StreamView::playlist_modified () } void -StreamView::playlist_changed (Diskstream *ds) +StreamView::playlist_changed (boost::shared_ptr ds) { ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds)); @@ -263,9 +263,7 @@ StreamView::diskstream_changed () Track *t; if ((t = _trackview.track()) != 0) { - Diskstream& ds = t->diskstream(); - /* XXX grrr: when will SigC++ allow me to bind references? */ - Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), &ds)); + Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), t->diskstream())); } else { Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::undisplay_diskstream)); } diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h index 5a0e10974f..8f7fb416be 100644 --- a/gtk2_ardour/streamview.h +++ b/gtk2_ardour/streamview.h @@ -111,13 +111,13 @@ protected: virtual void remove_region_view (ARDOUR::Region* ); void remove_rec_region (ARDOUR::Region*); - void display_diskstream (ARDOUR::Diskstream* ); + void display_diskstream (boost::shared_ptr); virtual void undisplay_diskstream (); virtual void redisplay_diskstream () = 0; void diskstream_changed (); void playlist_state_changed (ARDOUR::Change); - virtual void playlist_changed (ARDOUR::Diskstream* ); + virtual void playlist_changed (boost::shared_ptr); virtual void playlist_modified (); virtual void color_handler (ColorID, uint32_t) = 0; diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index 0cc2079d8e..18f8328cfd 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -59,12 +59,10 @@ class AudioDiskstream : public Diskstream public: AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable); AudioDiskstream (Session &, const XMLNode&); + ~AudioDiskstream(); const PBD::ID& id() const { return _id; } - // FIXME - AudioDiskstream& ref() { _refcnt++; return *this; } - float playback_buffer_load() const; float capture_buffer_load() const; @@ -176,9 +174,6 @@ class AudioDiskstream : public Diskstream private: - /* use unref() to destroy a diskstream */ - ~AudioDiskstream(); - struct ChannelInfo { Sample *playback_wrap_buffer; diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index 9892179085..33010dc880 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -46,7 +46,7 @@ class AudioTrack : public Track int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool can_record, bool rec_monitors_input); - AudioDiskstream& audio_diskstream() const; + boost::shared_ptr audio_diskstream() const; int use_diskstream (string name); int use_diskstream (const PBD::ID& id); @@ -71,7 +71,7 @@ class AudioTrack : public Track uint32_t n_process_buffers (); private: - int set_diskstream (AudioDiskstream&, void *); + int set_diskstream (boost::shared_ptr, void *); int deprecated_use_diskstream_connections (); void set_state_part_two (); void set_state_part_three (); diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index e7500fc7a2..00a0ce6b19 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -31,6 +31,8 @@ #include +#include + #include #include #include @@ -189,7 +191,6 @@ class AudioEngine : public sigc::trackable ARDOUR::Session *session; jack_client_t *_jack; std::string jack_client_name; - Glib::Mutex port_lock; Glib::Mutex _process_lock; Glib::Mutex session_remove_lock; Glib::Cond session_removed; @@ -208,7 +209,7 @@ class AudioEngine : public sigc::trackable int _usecs_per_cycle; typedef std::set Ports; - Ports ports; + SerializedRCUManager ports; int process_callback (jack_nframes_t nframes); void remove_all_ports (); diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index e0202a4fae..bcd418b452 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -43,7 +44,6 @@ #include #include - struct tm; namespace ARDOUR { @@ -54,7 +54,7 @@ class Session; class Playlist; class IO; -class Diskstream : public Stateful, public sigc::trackable + class Diskstream : public Stateful, public sigc::trackable, public PBD::Destructible { public: enum Flag { @@ -63,16 +63,16 @@ class Diskstream : public Stateful, public sigc::trackable Destructive = 0x4 }; + Diskstream (Session &, const string& name, Flag f = Recordable); + Diskstream (Session &, const XMLNode&); + virtual ~Diskstream(); + string name () const { return _name; } virtual int set_name (string str); ARDOUR::IO* io() const { return _io; } void set_io (ARDOUR::IO& io); - virtual Diskstream& ref() { _refcnt++; return *this; } - void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; } - uint32_t refcnt() const { return _refcnt; } - virtual float playback_buffer_load() const = 0; virtual float capture_buffer_load() const = 0; @@ -148,15 +148,11 @@ class Diskstream : public Stateful, public sigc::trackable static sigc::signal DiskOverrun; static sigc::signal DiskUnderrun; - static sigc::signal DiskstreamCreated; // XXX use a ref with sigc2 static sigc::signal*> DeleteSources; protected: friend class Session; - Diskstream (Session &, const string& name, Flag f = Recordable); - Diskstream (Session &, const XMLNode&); - /* the Session is the only point of access for these because they require * that the Session is "inactive" while they are called. */ @@ -187,9 +183,6 @@ class Diskstream : public Stateful, public sigc::trackable //private: - /** Use unref() to destroy a diskstream */ - virtual ~Diskstream(); - enum TransitionType { CaptureStart = 0, CaptureEnd @@ -304,8 +297,6 @@ class Diskstream : public Stateful, public sigc::trackable jack_nframes_t scrub_buffer_size; jack_nframes_t scrub_offset; - uint32_t _refcnt; - sigc::connection ports_created_c; sigc::connection plmod_connection; sigc::connection plstate_connection; diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index d1db818e40..ff7aa6184c 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -55,7 +56,7 @@ enum mute_type { MAIN_OUTS = 0x8 }; -class Route : public IO + class Route : public IO, public PBD::Destructible { protected: @@ -192,8 +193,6 @@ class Route : public IO sigc::signal active_changed; sigc::signal meter_change; - sigc::signal GoingAway; - /* gui's call this for their own purposes. */ sigc::signal gui_changed; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index d067de4e68..3763ebe91e 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -270,8 +270,9 @@ class Session : public sigc::trackable, public Stateful vector& get_silent_buffers (uint32_t howmany); vector& get_send_buffers () { return _send_buffers; } - Diskstream* diskstream_by_id (const PBD::ID& id); - Diskstream* diskstream_by_name (string name); + void add_diskstream (boost::shared_ptr); + boost::shared_ptr diskstream_by_id (const PBD::ID& id); + boost::shared_ptr diskstream_by_name (string name); bool have_captured() const { return _have_captured; } @@ -281,9 +282,8 @@ class Session : public sigc::trackable, public Stateful uint32_t get_next_diskstream_id() const { return n_diskstreams(); } uint32_t n_diskstreams() const; - typedef list DiskstreamList; - - typedef std::list > RouteList; + typedef std::list > DiskstreamList; + typedef std::list > RouteList; boost::shared_ptr get_routes() const { return routes.reader (); @@ -346,7 +346,6 @@ class Session : public sigc::trackable, public Stateful sigc::signal HaltOnXrun; sigc::signal > RouteAdded; - sigc::signal DiskstreamAdded; // FIXME: make a shared_ptr void request_roll (); void request_bounded_roll (jack_nframes_t start, jack_nframes_t end); @@ -1509,10 +1508,9 @@ class Session : public sigc::trackable, public Stateful /* disk-streams */ - DiskstreamList diskstreams; - mutable Glib::RWLock diskstream_lock; + SerializedRCUManager diskstreams; + uint32_t dstream_buffer_size; - void add_diskstream (Diskstream*); int load_diskstreams (const XMLNode&); /* routes stuff */ @@ -1580,7 +1578,7 @@ class Session : public sigc::trackable, public Stateful Playlist *XMLPlaylistFactory (const XMLNode&); void playlist_length_changed (Playlist *); - void diskstream_playlist_changed (Diskstream *); + void diskstream_playlist_changed (boost::shared_ptr); /* NAMED SELECTIONS */ diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 4e2af5c80e..ec444e78dc 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -19,6 +19,8 @@ #ifndef __ardour_track_h__ #define __ardour_track_h__ +#include + #include namespace ARDOUR { @@ -50,7 +52,7 @@ class Track : public Route virtual bool can_record(); - Diskstream& diskstream() const { return *_diskstream; } + boost::shared_ptr diskstream() const { return _diskstream; } virtual int use_diskstream (string name) = 0; virtual int use_diskstream (const PBD::ID& id) = 0; @@ -100,7 +102,7 @@ class Track : public Route virtual uint32_t n_process_buffers () = 0; - Diskstream *_diskstream; + boost::shared_ptr _diskstream; MeterPoint _saved_meter_point; TrackMode _mode; diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index d3e64104a0..baefeff377 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -71,8 +71,6 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream: use_new_playlist (); in_set_state = false; - - DiskstreamCreated (this); /* EMIT SIGNAL */ } AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) @@ -92,8 +90,6 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) if (destructive()) { use_destructive_playlist (); } - - DiskstreamCreated (this); /* EMIT SIGNAL */ } void diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 2f33012546..98a2262f86 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -55,9 +55,10 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive); } - AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags); - - set_diskstream (*ds, this); + boost::shared_ptr ds (new AudioDiskstream (_session, name, dflags)); + _session.add_diskstream (ds); + + set_diskstream (boost::dynamic_pointer_cast (ds), this); } AudioTrack::AudioTrack (Session& sess, const XMLNode& node) @@ -73,18 +74,18 @@ AudioTrack::~AudioTrack () int AudioTrack::deprecated_use_diskstream_connections () { - AudioDiskstream& diskstream = audio_diskstream(); + boost::shared_ptr diskstream = audio_diskstream(); - if (diskstream.deprecated_io_node == 0) { + if (diskstream->deprecated_io_node == 0) { return 0; } const XMLProperty* prop; - XMLNode& node (*diskstream.deprecated_io_node); + XMLNode& node (*diskstream->deprecated_io_node); /* don't do this more than once. */ - diskstream.deprecated_io_node = 0; + diskstream->deprecated_io_node = 0; set_input_minimum (-1); set_input_maximum (-1); @@ -125,17 +126,13 @@ AudioTrack::deprecated_use_diskstream_connections () } int -AudioTrack::set_diskstream (AudioDiskstream& ds, void *src) +AudioTrack::set_diskstream (boost::shared_ptr ds, void *src) { - if (_diskstream) { - _diskstream->unref(); - } - - _diskstream = &ds.ref(); + _diskstream = ds; _diskstream->set_io (*this); _diskstream->set_destructive (_mode == Destructive); - if (audio_diskstream().deprecated_io_node) { + if (audio_diskstream()->deprecated_io_node) { if (!connecting_legal) { ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections)); @@ -158,33 +155,33 @@ AudioTrack::set_diskstream (AudioDiskstream& ds, void *src) int AudioTrack::use_diskstream (string name) { - AudioDiskstream *dstream; + boost::shared_ptr dstream; - if ((dstream = dynamic_cast(_session.diskstream_by_name (name))) == 0) { - error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg; + if ((dstream = boost::dynamic_pointer_cast(_session.diskstream_by_name (name))) == 0) { + error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg; return -1; } - return set_diskstream (*dstream, this); + return set_diskstream (dstream, this); } int AudioTrack::use_diskstream (const PBD::ID& id) { - AudioDiskstream *dstream; + boost::shared_ptr dstream; - if ((dstream = dynamic_cast(_session.diskstream_by_id (id))) == 0) { + if ((dstream = boost::dynamic_pointer_cast (_session.diskstream_by_id (id))) == 0) { error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg; return -1; } - return set_diskstream (*dstream, this); + return set_diskstream (dstream, this); } -AudioDiskstream& +boost::shared_ptr AudioTrack::audio_diskstream() const { - return *dynamic_cast(_diskstream); + return boost::dynamic_pointer_cast(_diskstream); } int @@ -434,7 +431,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf return 0; } - audio_diskstream().check_record_status (start_frame, nframes, can_record); + audio_diskstream()->check_record_status (start_frame, nframes, can_record); bool send_silence; @@ -501,7 +498,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram Sample* b; Sample* tmpb; jack_nframes_t transport_frame; - AudioDiskstream& diskstream = audio_diskstream(); + boost::shared_ptr diskstream = audio_diskstream(); { Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK); @@ -528,13 +525,13 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram playback distance to zero, thus causing diskstream::commit to do nothing. */ - return diskstream.process (transport_frame, 0, 0, can_record, rec_monitors_input); + return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input); } _silent = false; apply_gain_automation = false; - if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) { + if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) { silence (nframes, offset); @@ -547,7 +544,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram just_meter_input (start_frame, end_frame, nframes, offset); } - if (diskstream.record_enabled() && !can_record && !_session.get_auto_input()) { + if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) { /* not actually recording, but we want to hear the input material anyway, at least potentially (depending on monitoring options) @@ -555,7 +552,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram passthru (start_frame, end_frame, nframes, offset, 0, true); - } else if ((b = diskstream.playback_buffer(0)) != 0) { + } else if ((b = diskstream->playback_buffer(0)) != 0) { /* XXX is it true that the earlier test on n_outputs() @@ -577,8 +574,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram for (i = 0, n = 1; i < limit; ++i, ++n) { memcpy (bufs[i], b, sizeof (Sample) * nframes); - if (n < diskstream.n_channels()) { - tmpb = diskstream.playback_buffer(n); + if (n < diskstream->n_channels()) { + tmpb = diskstream->playback_buffer(n); if (tmpb!=0) { b = tmpb; } @@ -587,7 +584,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */ - if (!diskstream.record_enabled() && _session.transport_rolling()) { + if (!diskstream->record_enabled() && _session.transport_rolling()) { Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK); if (am.locked() && gain_automation_playback()) { @@ -623,7 +620,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac silence (nframes, offset); - return audio_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input); + return audio_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input); } int @@ -637,12 +634,12 @@ AudioTrack::export_stuff (vector& buffers, uint32_t nbufs, jack_nframes gain_t this_gain = _gain; vector::iterator bi; Sample * b; - AudioDiskstream& diskstream = audio_diskstream(); + boost::shared_ptr diskstream = audio_diskstream(); Glib::RWLock::ReaderLock rlock (redirect_lock); // FIXME - AudioPlaylist* const apl = dynamic_cast(diskstream.playlist()); + AudioPlaylist* const apl = dynamic_cast(diskstream->playlist()); assert(apl); if (apl->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) { @@ -654,7 +651,7 @@ AudioTrack::export_stuff (vector& buffers, uint32_t nbufs, jack_nframes b = buffers[0]; ++bi; for (; bi != buffers.end(); ++bi, ++n) { - if (n < diskstream.n_channels()) { + if (n < diskstream->n_channels()) { if (apl->read ((*bi), mix_buffer, gain_buffer, start, nframes, n) != nframes) { return -1; } @@ -751,9 +748,9 @@ AudioTrack::freeze (InterThreadInfo& itt) string dir; AudioRegion* region; string region_name; - AudioDiskstream& diskstream = audio_diskstream(); + boost::shared_ptr diskstream = audio_diskstream(); - if ((_freeze_record.playlist = dynamic_cast(diskstream.playlist())) == 0) { + if ((_freeze_record.playlist = dynamic_cast(diskstream->playlist())) == 0) { return; } @@ -821,13 +818,13 @@ AudioTrack::freeze (InterThreadInfo& itt) (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags), false); - new_playlist->set_orig_diskstream_id (diskstream.id()); + new_playlist->set_orig_diskstream_id (diskstream->id()); new_playlist->add_region (*region, 0); new_playlist->set_frozen (true); region->set_locked (true); - diskstream.use_playlist (dynamic_cast(new_playlist)); - diskstream.set_record_enabled (false); + diskstream->use_playlist (dynamic_cast(new_playlist)); + diskstream->set_record_enabled (false); _freeze_record.state = Frozen; FreezeChange(); /* EMIT SIGNAL */ @@ -837,7 +834,7 @@ void AudioTrack::unfreeze () { if (_freeze_record.playlist) { - audio_diskstream().use_playlist (_freeze_record.playlist); + audio_diskstream()->use_playlist (_freeze_record.playlist); if (_freeze_record.have_mementos) { diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 982a7c5971..4a4659d1df 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -47,6 +47,7 @@ jack_nframes_t Port::_short_over_length = 2; jack_nframes_t Port::_long_over_length = 10; AudioEngine::AudioEngine (string client_name) + : ports (new Ports) { session = 0; session_remove_pending = false; @@ -270,7 +271,10 @@ AudioEngine::process_callback (jack_nframes_t nframes) } if (last_monitor_check + monitor_check_interval < next_processed_frames) { - for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { + + boost::shared_ptr p = ports.reader(); + + for (Ports::iterator i = p->begin(); i != p->end(); ++i) { Port *port = (*i); bool x; @@ -329,7 +333,9 @@ AudioEngine::jack_bufsize_callback (jack_nframes_t nframes) _usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0); last_monitor_check = 0; - for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { + boost::shared_ptr p = ports.reader(); + + for (Ports::iterator i = p->begin(); i != p->end(); ++i) { (*i)->reset(); } @@ -400,15 +406,19 @@ AudioEngine::register_input_port (DataType type, const string& portname) } } - jack_port_t *p = jack_port_register (_jack, portname.c_str(), - type.to_jack_type(), JackPortIsInput, 0); + jack_port_t *p = jack_port_register (_jack, portname.c_str(), type.to_jack_type(), JackPortIsInput, 0); if (p) { Port *newport; + if ((newport = new Port (p)) != 0) { - ports.insert (ports.begin(), newport); + RCUWriter writer (ports); + boost::shared_ptr ps = writer.get_copy (); + ps->insert (ps->begin(), newport); + /* writer goes out of scope, forces update */ } + return newport; } else { @@ -436,8 +446,19 @@ AudioEngine::register_output_port (DataType type, const string& portname) if ((p = jack_port_register (_jack, portname.c_str(), type.to_jack_type(), JackPortIsOutput, 0)) != 0) { - Port *newport = new Port (p); - ports.insert (ports.begin(), newport); + + Port *newport = 0; + + { + RCUWriter writer (ports); + boost::shared_ptr ps = writer.get_copy (); + + newport = new Port (p); + ps->insert (ps->begin(), newport); + + /* writer goes out of scope, forces update */ + } + return newport; } else { @@ -465,12 +486,20 @@ AudioEngine::unregister_port (Port *port) int ret = jack_port_unregister (_jack, port->_port); if (ret == 0) { - - for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { - if ((*i) == port) { - ports.erase (i); - break; + + { + + RCUWriter writer (ports); + boost::shared_ptr ps = writer.get_copy (); + + for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) { + if ((*i) == port) { + ps->erase (i); + break; + } } + + /* writer goes out of scope, forces update */ } remove_connections_for (port); @@ -613,7 +642,9 @@ AudioEngine::get_port_by_name (const string& portname, bool keep) /* check to see if we have a Port for this name already */ - for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { + boost::shared_ptr pr = ports.reader(); + + for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) { if (portname == (*i)->name()) { return (*i); } @@ -623,11 +654,20 @@ AudioEngine::get_port_by_name (const string& portname, bool keep) if ((p = jack_port_by_name (_jack, portname.c_str())) != 0) { Port *newport = new Port (p); - if (keep && newport->is_mine (_jack)) { - ports.insert (newport); + + { + if (keep && newport->is_mine (_jack)) { + RCUWriter writer (ports); + boost::shared_ptr ps = writer.get_copy (); + ps->insert (newport); + /* writer goes out of scope, forces update */ + } } + return newport; + } else { + return 0; } } @@ -827,12 +867,19 @@ AudioEngine::remove_all_ports () /* process lock MUST be held */ if (_jack) { - for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { + boost::shared_ptr p = ports.reader(); + + for (Ports::iterator i = p->begin(); i != p->end(); ++i) { jack_port_unregister (_jack, (*i)->_port); } } - ports.clear (); + { + RCUWriter writer (ports); + boost::shared_ptr ps = writer.get_copy (); + ps->clear (); + } + port_connections.clear (); } @@ -932,7 +979,7 @@ AudioEngine::reconnect_to_jack () if (_jack) { disconnect_from_jack (); /* XXX give jackd a chance */ - Glib::usleep (250000); + Glib::usleep (250000); } if (connect_to_jack (jack_client_name)) { @@ -942,7 +989,9 @@ AudioEngine::reconnect_to_jack () Ports::iterator i; - for (i = ports.begin(); i != ports.end(); ++i) { + boost::shared_ptr p = ports.reader (); + + for (i = p->begin(); i != p->end(); ++i) { /* XXX hack hack hack */ @@ -964,8 +1013,9 @@ AudioEngine::reconnect_to_jack () } } - if (i != ports.end()) { - for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { + if (i != p->end()) { + /* failed */ + for (Ports::iterator i = p->begin(); i != p->end(); ++i) { jack_port_unregister (_jack, (*i)->_port); } return -1; diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc index e48f103b9f..dc08979458 100644 --- a/libs/ardour/auditioner.cc +++ b/libs/ardour/auditioner.cc @@ -49,7 +49,7 @@ Auditioner::Auditioner (Session& s) } if (right.length()) { - audio_diskstream().add_channel(); + audio_diskstream()->add_channel(); add_output_port (right, this, DataType::AUDIO); } @@ -117,11 +117,11 @@ Auditioner::audition_region (AudioRegion& region) _diskstream->playlist()->add_region (*the_region, 0, 1, false); while (_diskstream->n_channels() < the_region->n_channels()) { - audio_diskstream().add_channel (); + audio_diskstream()->add_channel (); } while (_diskstream->n_channels() > the_region->n_channels()) { - audio_diskstream().remove_channel (); + audio_diskstream()->remove_channel (); } /* force a panner reset now that we have all channels */ diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index b2d481077f..151ff5bd3e 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -63,7 +63,6 @@ using namespace PBD; */ jack_nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256; -sigc::signal Diskstream::DiskstreamCreated; sigc::signal*> Diskstream::DeleteSources; sigc::signal Diskstream::DiskOverrun; sigc::signal Diskstream::DiskUnderrun; @@ -86,7 +85,6 @@ Diskstream::Diskstream (Session& sess, const XMLNode& node) void Diskstream::init (Flag f) { - _refcnt = 0; _flags = f; _io = 0; _alignment_style = ExistingMaterial; diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index b47981a47e..02c62eefa1 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -111,7 +111,8 @@ Route::init () Route::~Route () { - GoingAway (); /* EMIT SIGNAL */ + cerr << "deleting route " << _name << endl; + clear_redirects (this); if (_control_outs) { 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 (); diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index 6509a783bb..5d691a7425 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -248,11 +248,11 @@ Session::butler_thread_work () gettimeofday (&begin, 0); - Glib::RWLock::ReaderLock dsm (diskstream_lock); + boost::shared_ptr dsl = diskstreams.reader (); - for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) { + for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) { - Diskstream* const ds = *i; + boost::shared_ptr ds = *i; switch (ds->do_refill ()) { case 0: @@ -271,7 +271,7 @@ Session::butler_thread_work () } - if (i != diskstreams.end()) { + if (i != dsl->end()) { /* we didn't get to all the streams */ disk_work_outstanding = true; } @@ -293,7 +293,7 @@ Session::butler_thread_work () compute_io = true; gettimeofday (&begin, 0); - for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) { + for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) { // cerr << "write behind for " << (*i)->name () << endl; switch ((*i)->do_flush (Session::ButlerContext)) { @@ -322,7 +322,7 @@ Session::butler_thread_work () request_stop (); } - if (i != diskstreams.end()) { + if (i != dsl->end()) { /* we didn't get to all the streams */ disk_work_outstanding = true; } @@ -349,7 +349,7 @@ Session::butler_thread_work () Glib::Mutex::Lock lm (butler_request_lock); if (butler_should_run && (disk_work_outstanding || transport_work_requested())) { -// for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { +// for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { // cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl; // } @@ -388,8 +388,8 @@ Session::overwrite_some_buffers (Diskstream* ds) } else { - Glib::RWLock::ReaderLock dm (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) { (*i)->set_pending_overwrite (true); } } diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc index b39c4f2218..98653314b0 100644 --- a/libs/ardour/session_export.cc +++ b/libs/ardour/session_export.cc @@ -495,8 +495,9 @@ Session::prepare_to_export (AudioExportSpecification& spec) /* get everyone to the right position */ { - 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) { if ((*i)-> seek (spec.start_frame, true)) { error << string_compose (_("%1: cannot seek to %2 for export"), (*i)->name(), spec.start_frame) diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 88b111a1fb..68ad11cf42 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -66,7 +66,8 @@ Session::process (jack_nframes_t nframes) void Session::prepare_diskstreams () { - 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)->prepare (); } } @@ -141,7 +142,8 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset) call path, so make sure we release any outstanding locks here before we return failure. */ - for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) { + boost::shared_ptr dsl = diskstreams.reader(); + for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) { (*ids)->recover (); } @@ -181,7 +183,8 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset) call path, so make sure we release any outstanding locks here before we return failure. */ - for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) { + boost::shared_ptr dsl = diskstreams.reader(); + for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) { (*ids)->recover (); } @@ -200,7 +203,8 @@ Session::commit_diskstreams (jack_nframes_t nframes, bool &needs_butler) float pworst = 1.0f; float cworst = 1.0f; - 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)->hidden()) { continue; @@ -284,12 +288,10 @@ Session::process_with_events (jack_nframes_t nframes) end_frame = _transport_frame + nframes; { - Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK); - Event* this_event; Events::iterator the_next_one; - if (!dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) { + if (post_transport_work & (PostTransportLocate|PostTransportStop)) { no_roll (nframes, 0); return; } @@ -560,17 +562,18 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset) if (slave_state == Waiting) { // cerr << "waiting at " << slave_transport_frame << endl; - Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK); - - if (dsm.locked() && slave_transport_frame >= slave_wait_end) { + + if (slave_transport_frame >= slave_wait_end) { // cerr << "\tstart at " << _transport_frame << endl; slave_state = Running; bool ok = true; jack_nframes_t frame_delta = slave_transport_frame - _transport_frame; + + 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)->can_internal_playback_seek (frame_delta)) { ok = false; break; @@ -578,7 +581,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset) } if (ok) { - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { (*i)->internal_playback_seek (frame_delta); } _transport_frame += frame_delta; @@ -682,12 +685,6 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset) bool need_butler; - Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK); - if (!dsm.locked()) { - goto noroll; - } - - prepare_diskstreams (); silent_process_routes (nframes, offset); commit_diskstreams (nframes, need_butler); @@ -733,9 +730,7 @@ Session::process_without_events (jack_nframes_t nframes) long frames_moved; { - Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK); - - if (!dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) { + if (post_transport_work & (PostTransportLocate|PostTransportStop)) { no_roll (nframes, 0); return; } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 5a75c04b3f..6770428c65 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -264,7 +264,6 @@ Session::first_stage_init (string fullpath, string snapshot_name) AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source)); Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist)); Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect)); - AudioDiskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream)); NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection)); Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve)); AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list)); @@ -626,11 +625,10 @@ Session::load_diskstreams (const XMLNode& node) for (citer = clist.begin(); citer != clist.end(); ++citer) { - AudioDiskstream* dstream; try { - dstream = new AudioDiskstream (*this, **citer); - /* added automatically by AudioDiskstreamCreated handler */ + boost::shared_ptr dstream (new AudioDiskstream (*this, **citer)); + add_diskstream (dstream); } catch (failed_constructor& err) { @@ -1388,8 +1386,8 @@ Session::state(bool full_state) child = node->add_child ("DiskStreams"); { - Glib::RWLock::ReaderLock dl (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)->hidden()) { child->add_child_nocopy ((*i)->get_state()); } diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 7c2b4f1c6f..8e0522c19d 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -192,8 +192,8 @@ Session::realtime_stop (bool abort) void Session::butler_transport_work () { - Glib::RWLock::ReaderLock dsm (diskstream_lock); boost::shared_ptr r = routes.reader (); + boost::shared_ptr dsl = diskstreams.reader(); if (post_transport_work & PostTransportCurveRealloc) { for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { @@ -202,7 +202,7 @@ Session::butler_transport_work () } if (post_transport_work & PostTransportInputChange) { - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { (*i)->non_realtime_input_change (); } } @@ -218,7 +218,7 @@ Session::butler_transport_work () cumulative_rf_motion = 0; reset_rf_scale (0); - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if (!(*i)->hidden()) { if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) { (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed())); @@ -248,9 +248,9 @@ Session::butler_transport_work () void Session::non_realtime_set_speed () { - 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) { (*i)->non_realtime_set_speed (); } } @@ -258,9 +258,9 @@ Session::non_realtime_set_speed () void Session::non_realtime_overwrite () { - 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)->pending_overwrite) { (*i)->overwrite_existing_buffers (); } @@ -276,7 +276,9 @@ Session::non_realtime_stop (bool abort) did_record = false; - 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)->get_captured_frames () != 0) { did_record = true; break; @@ -331,7 +333,7 @@ Session::non_realtime_stop (bool abort) _have_captured = true; } - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { (*i)->transport_stopped (*now, xnow, abort); } @@ -370,7 +372,7 @@ Session::non_realtime_stop (bool abort) } #endif - for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if (!(*i)->hidden()) { if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) { (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed())); @@ -497,7 +499,8 @@ Session::set_auto_loop (bool yn) if (seamless_loop) { // set all diskstreams to use internal looping - 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)->hidden()) { (*i)->set_loop (loc); } @@ -505,7 +508,8 @@ Session::set_auto_loop (bool yn) } else { // set all diskstreams to NOT use internal looping - 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)->hidden()) { (*i)->set_loop (0); } @@ -535,7 +539,8 @@ Session::set_auto_loop (bool yn) clear_events (Event::AutoLoop); // set all diskstreams to NOT use internal looping - 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)->hidden()) { (*i)->set_loop (0); } @@ -648,12 +653,10 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b if (with_roll) { /* switch from input if we're going to roll */ if (Config->get_use_hardware_monitoring()) { - /* Even though this is 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 ()) { //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (!auto_input); @@ -663,12 +666,9 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b } else { /* otherwise we're going to stop, so do the opposite */ if (Config->get_use_hardware_monitoring()) { - /* Even though this is 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 ()) { //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (true); @@ -707,12 +707,9 @@ Session::set_transport_speed (float speed, bool abort) if (Config->get_use_hardware_monitoring()) { - /* Even though this is 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 ()) { //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (true); @@ -733,12 +730,10 @@ Session::set_transport_speed (float speed, bool abort) } if (Config->get_use_hardware_monitoring()) { - /* Even though this is 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 (auto_input && (*i)->record_enabled ()) { //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (false); @@ -789,7 +784,8 @@ Session::set_transport_speed (float speed, bool abort) _last_transport_speed = _transport_speed; _transport_speed = speed; - 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)->realtime_set_speed ((*i)->speed(), true)) { post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed); } @@ -879,7 +875,8 @@ Session::actually_start_transport () transport_sub_state |= PendingDeclickIn; _transport_speed = 1.0; - 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)->realtime_set_speed ((*i)->speed(), true); } @@ -1009,7 +1006,8 @@ Session::set_slave_source (SlaveSource src, jack_nframes_t frame) _slave_type = src; - 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)->hidden()) { if ((*i)->realtime_set_speed ((*i)->speed(), true)) { non_rt_required = true; @@ -1200,7 +1198,6 @@ Session::update_latency_compensation (bool with_stop, bool abort) return; } - Glib::RWLock::ReaderLock lm2 (diskstream_lock); _worst_track_latency = 0; boost::shared_ptr r = routes.reader (); @@ -1238,7 +1235,9 @@ Session::update_latency_compensation (bool with_stop, bool abort) /* reflect any changes in latencies into capture offsets */ - 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 (); } } diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 58d8c1b306..c8633d9e52 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -41,7 +41,6 @@ using namespace PBD; Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type) : Route (sess, name, 1, -1, -1, -1, flag, default_type) - , _diskstream (0) , _rec_enable_control (*this) { _declickable = true; @@ -52,7 +51,6 @@ Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, Data Track::Track (Session& sess, const XMLNode& node, DataType default_type) : Route (sess, "to be renamed", 0, 0, -1, -1, Route::Flag(0), default_type) - , _diskstream (0) , _rec_enable_control (*this) { _freeze_record.state = NoFreeze; @@ -62,9 +60,6 @@ Track::Track (Session& sess, const XMLNode& node, DataType default_type) Track::~Track () { - if (_diskstream) { - _diskstream->unref(); - } } void diff --git a/libs/pbd/pbd/rcu.h b/libs/pbd/pbd/rcu.h index 58a92a206a..e81db8ba87 100644 --- a/libs/pbd/pbd/rcu.h +++ b/libs/pbd/pbd/rcu.h @@ -5,8 +5,7 @@ #include "glibmm/thread.h" #include - - + template class RCUManager { @@ -43,7 +42,7 @@ public: } - virtual boost::shared_ptr write_copy () + boost::shared_ptr write_copy () { m_lock.lock(); @@ -64,11 +63,11 @@ public: current_write_old = RCUManager::m_rcu_value; boost::shared_ptr new_copy (new T(**current_write_old)); - + return new_copy; } - virtual bool update (boost::shared_ptr new_value) + bool update (boost::shared_ptr new_value) { // we hold the lock at this point effectively blocking // other writers. @@ -98,6 +97,11 @@ public: return ret; } + + void flush () { + Glib::Mutex::Lock lm (m_lock); + m_dead_wood.clear (); + } private: Glib::Mutex m_lock; -- cgit v1.2.3