RCU-ification of AudioEngine port list, and DiskStreams. not well tested, but basical...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 16 Aug 2006 01:19:06 +0000 (01:19 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 16 Aug 2006 01:19:06 +0000 (01:19 +0000)
git-svn-id: svn://localhost/ardour2/trunk@828 d708f5d6-7413-0410-9779-e7cbd77b26cf

36 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/audio_streamview.cc
gtk2_ardour/audio_streamview.h
gtk2_ardour/editor.cc
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/editor_timefx.cc
gtk2_ardour/playlist_selector.cc
gtk2_ardour/plugin_selector.cc
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
gtk2_ardour/streamview.cc
gtk2_ardour/streamview.h
libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/audio_track.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/diskstream.h
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/ardour/track.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_track.cc
libs/ardour/audioengine.cc
libs/ardour/auditioner.cc
libs/ardour/diskstream.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_butler.cc
libs/ardour/session_export.cc
libs/ardour/session_process.cc
libs/ardour/session_state.cc
libs/ardour/session_transport.cc
libs/ardour/track.cc
libs/pbd/pbd/rcu.h

index e5367d6280f633b88ec6d707e0c66cf142005c27..bca27c7231ab978bf0ebc083f8941032e2b8dc8f 100644 (file)
@@ -545,7 +545,7 @@ void
 ARDOUR_UI::count_recenabled_diskstreams (Route& route)
 {
        Track* track = dynamic_cast<Track*>(&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<Track*>(r.get())) != 0) {
-                       t->diskstream().set_record_enabled (!t->diskstream().record_enabled());
+                       t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
                }
        }
        if (session == 0) {
index 297c9c3c65e60a965dd2c2290c1ef8b8bf6ebf39..c8d0d70a7d6a14d1e069b2318ecc341c658260c2 100644 (file)
@@ -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;
index 25f3068a813d39c04d0b38157e98f79dee0e6c7c..c90480c1dd9fbae244f4d5be8ba440c1b4440c6d 100644 (file)
@@ -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);
        }
index 82349947c684e8154b729154d42e2f9952860a39..d650df1563bf82af3d5b3554f6599caadb4dcddd 100644 (file)
@@ -225,7 +225,7 @@ AudioStreamView::playlist_modified ()
 }
 
 void
-AudioStreamView::playlist_changed (Diskstream *ds)
+AudioStreamView::playlist_changed (boost::shared_ptr<Diskstream> 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<AudioDiskstream*>(_trackview.get_diskstream());
+                               boost::shared_ptr<AudioDiskstream> ads = boost::dynamic_pointer_cast<AudioDiskstream>(_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<AudioDiskstream> 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;
index 05ce8125f618d514b155851076b5d808f80b769c..edda221bbdb894352aaa0e3858a4da3ca18e897e 100644 (file)
@@ -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<ARDOUR::Diskstream>);
 
        void add_crossfade (ARDOUR::Crossfade*);
        void remove_crossfade (ARDOUR::Crossfade*);
index 050ec6be90029f230774acaf0b1118966670f1a4..2be8b2d73b5aec31371cf37bb548c944d36c5084 100644 (file)
@@ -1596,7 +1596,7 @@ Editor::build_track_region_context_menu (jack_nframes_t frame)
        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
 
        if (atv) {
-               Diskstream* ds;
+               boost::shared_ptr<Diskstream> 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<AudioTimeAxisView*> (clicked_trackview);
 
        if (atv) {
-               Diskstream* ds;
+               boost::shared_ptr<Diskstream> ds;
                Playlist* pl;
                AudioPlaylist* apl;
 
@@ -3020,7 +3020,7 @@ Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32
        Playlist* pl;
        vector<Region*> results;
        RegionView* marv;
-       Diskstream* ds;
+       boost::shared_ptr<Diskstream> 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<Region*> results;
                        RegionView* marv;
-                       Diskstream* ds;
+                       boost::shared_ptr<Diskstream> ds;
                        
                        if ((ds = tatv->get_diskstream()) == 0) {
                                /* bus */
index 8887135374e0248b53a60d2206442aad16a41267..b6fdefa4d3806d2a49a0421f5e1fb37a4601d1e5 100644 (file)
@@ -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<AudioTrack> 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<AudioTrack> 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;
        }
        }
index a3288ea8d0daa0ceb2126b904e3fbbbabfc3d6f3..caa9698b8c8679ded73f28423ec6342b38bf5e15 100644 (file)
@@ -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;
                }
index 8eaac7cb9d3e74814db7bab3523fc1dd3075d03b..68227d193c281fb0f07dc2de54643dd247a9bfa9 100644 (file)
@@ -90,7 +90,7 @@ void
 PlaylistSelector::show_for (RouteUI* ruix)
 {
        vector<const char*> item;
-       Diskstream* this_ds;
+       boost::shared_ptr<Diskstream> 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<Diskstream> 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 ();
        }
index 2ebaaae100572efd0ed2ccd54e8b77993e0531a8..6c72767b112a4838fad4abb385071788009257c3 100644 (file)
@@ -226,7 +226,7 @@ PluginSelector::set_correct_focus()
                au_display.grab_focus();
                return;
        }
-#endif;
+#endif
 }
 
 void
index 05f832700ea90b669d394a18888956eb46013011..e7a6df2f273c2ec0f8da018f91845e4e9f9bacec 100644 (file)
@@ -728,7 +728,7 @@ RouteTimeAxisView::rename_current_playlist ()
        ArdourPrompter prompter (true);
        string name;
 
-       Diskstream *const ds = get_diskstream();
+       boost::shared_ptr<Diskstream> 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<Diskstream> 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<Diskstream> 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<Diskstream> ds = get_diskstream();
        if (!ds || ds->destructive())
                return;
 
@@ -963,7 +963,7 @@ RouteTimeAxisView::name() const
 Playlist *
 RouteTimeAxisView::playlist () const 
 {
-       Diskstream *ds;
+       boost::shared_ptr<Diskstream> 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<Diskstream> 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<Diskstream> ds = get_diskstream();
        Playlist* playlist;
        bool ret = false;
 
index 998385f66b1e3263365bc60efd65e93da54f24f8..b2fdcaf7d4b9c1e9c7570db31c33ee4b14fa496d 100644 (file)
@@ -74,7 +74,7 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
        if (is_track()) {
                boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_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<AudioTrack*>(_route.get());
 }
 
-Diskstream*
+boost::shared_ptr<Diskstream>
 RouteUI::get_diskstream () const
 {
        boost::shared_ptr<Track> t;
 
        if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
-               return &t->diskstream();
+               return t->diskstream();
        } else {
-               return 0;
+               return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
        }
 }
 
index 7415eddad6b58367eb13217da207e515c4e91a4e..8a257028e9e7b868c216adc551630e6a1535615d 100644 (file)
@@ -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<ARDOUR::Diskstream> get_diskstream() const;
 
        string name() const;
 
index d1d163d7a2ed746032a42f80b3ed39a180c1d4aa..733e27c4ab98d0606ce06d49b1de01e8ff0b007e 100644 (file)
@@ -206,7 +206,7 @@ StreamView::undisplay_diskstream ()
 }
 
 void
-StreamView::display_diskstream (Diskstream *ds)
+StreamView::display_diskstream (boost::shared_ptr<Diskstream> 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<Diskstream> 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));
        }
index 5a0e10974f9a8c3f472c9123629c24ca403aad99..8f7fb416bef79b4a61ddacbe3b306312f04d66a8 100644 (file)
@@ -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<ARDOUR::Diskstream>);
        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<ARDOUR::Diskstream>);
        virtual void playlist_modified ();
        
        virtual void color_handler (ColorID, uint32_t) = 0;
index 0cc2079d8e87e6a5ed93b2e80e942f33797d4029..18f8328cfd55cd102621a44a0f7e9cc1b0219bcf 100644 (file)
@@ -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;
index 9892179085cdcb39173e170165b7d23a69dec654..33010dc8804a86b371f5ca13ac2d51d6514d353e 100644 (file)
@@ -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<AudioDiskstream> 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<AudioDiskstream>, void *);
        int  deprecated_use_diskstream_connections ();
        void set_state_part_two ();
        void set_state_part_three ();
index e7500fc7a2e2d17c7f7dd7d0ac545aedec4f9727..00a0ce6b1940d2b3ce56e816ccf3e88dc87600c3 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <glibmm/thread.h>
 
+#include <pbd/rcu.h>
+
 #include <ardour/ardour.h>
 #include <jack/jack.h>
 #include <jack/transport.h>
@@ -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<Port*> Ports;
-       Ports ports;
+       SerializedRCUManager<Ports> ports;
 
        int    process_callback (jack_nframes_t nframes);
        void   remove_all_ports ();
index e0202a4fae448a96df7d3f31142366de1e75b412..bcd418b452bf3ca2abc848a9a275e969b421690c 100644 (file)
@@ -34,6 +34,7 @@
 #include <pbd/fastlog.h>
 #include <pbd/ringbufferNPT.h>
 #include <pbd/stateful.h>
+#include <pbd/destructible.h>
 
 #include <ardour/ardour.h>
 #include <ardour/configuration.h>
@@ -43,7 +44,6 @@
 #include <ardour/port.h>
 #include <ardour/utils.h>
 
-
 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<void>                DiskOverrun;
        static sigc::signal<void>                DiskUnderrun;
-       static sigc::signal<void,Diskstream*>    DiskstreamCreated; // XXX use a ref with sigc2
        static sigc::signal<void,list<Source*>*> 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;
index d1db818e4004c1d29a755a7b6b1458e0436e235f..ff7aa6184c47052987c4e083ebdc4556c5acad46 100644 (file)
@@ -35,6 +35,7 @@
 #include <pbd/undo.h>
 #include <pbd/stateful.h> 
 #include <pbd/controllable.h>
+#include <pbd/destructible.h>
 
 #include <ardour/ardour.h>
 #include <ardour/io.h>
@@ -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<void>       active_changed;
        sigc::signal<void,void*> meter_change;
 
-       sigc::signal<void> GoingAway;
-
        /* gui's call this for their own purposes. */
 
        sigc::signal<void,std::string,void*> gui_changed;
index d067de4e68c0d94c43989015435dec006845e9e3..3763ebe91e15ccf728267b33006d2755cfff765d 100644 (file)
@@ -270,8 +270,9 @@ class Session : public sigc::trackable, public Stateful
        vector<Sample*>& get_silent_buffers (uint32_t howmany);
        vector<Sample*>& 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<Diskstream>);
+       boost::shared_ptr<Diskstream> diskstream_by_id (const PBD::ID& id);
+       boost::shared_ptr<Diskstream> 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<Diskstream *> DiskstreamList;
-
-       typedef std::list<boost::shared_ptr<Route> > RouteList; 
+       typedef std::list<boost::shared_ptr<Diskstream> > DiskstreamList;
+       typedef std::list<boost::shared_ptr<Route> >      RouteList; 
 
        boost::shared_ptr<RouteList> get_routes() const {
                return routes.reader ();
@@ -346,7 +346,6 @@ class Session : public sigc::trackable, public Stateful
        sigc::signal<void> HaltOnXrun;
 
        sigc::signal<void,boost::shared_ptr<Route> > RouteAdded;
-       sigc::signal<void,Diskstream*> 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<DiskstreamList>  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<Diskstream>);
 
        /* NAMED SELECTIONS */
 
index 4e2af5c80eb9b1b035b357d03c51a701832f9933..ec444e78dc34d5f9c0cb1f0cf21528e06df991e9 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef __ardour_track_h__
 #define __ardour_track_h__
 
+#include <boost/shared_ptr.hpp>
+
 #include <ardour/route.h>
 
 namespace ARDOUR {
@@ -50,7 +52,7 @@ class Track : public Route
 
        virtual bool can_record();
 
-       Diskstream& diskstream() const { return *_diskstream; }
+       boost::shared_ptr<Diskstream> 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> _diskstream;
        MeterPoint  _saved_meter_point;
        TrackMode   _mode;
 
index d3e64104a09937a362c4ab6ef3d0321be6ec00e2..baefeff377e91e82f8ff51682d088c140ab86a2e 100644 (file)
@@ -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
index 2f33012546efc1f509922fe22984508f67e500f0..98a2262f8683e6498ca5781ecb99ecc6d2643a4c 100644 (file)
@@ -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<AudioDiskstream> ds (new AudioDiskstream (_session, name, dflags));
+       _session.add_diskstream (ds);
+
+       set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (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<AudioDiskstream> 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<AudioDiskstream> 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<AudioDiskstream> dstream;
 
-       if ((dstream = dynamic_cast<AudioDiskstream*>(_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<AudioDiskstream>(_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<AudioDiskstream> dstream;
 
-       if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_id (id))) == 0) {
+       if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream> (_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<AudioDiskstream>
 AudioTrack::audio_diskstream() const
 {
-       return *dynamic_cast<AudioDiskstream*>(_diskstream);
+       return boost::dynamic_pointer_cast<AudioDiskstream>(_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<AudioDiskstream> 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<Sample*>& buffers, uint32_t nbufs, jack_nframes
        gain_t this_gain = _gain;
        vector<Sample*>::iterator bi;
        Sample * b;
-       AudioDiskstream& diskstream = audio_diskstream();
+       boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
        
        Glib::RWLock::ReaderLock rlock (redirect_lock);
 
        // FIXME
-       AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream.playlist());
+       AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream->playlist());
        assert(apl);
 
        if (apl->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) {
@@ -654,7 +651,7 @@ AudioTrack::export_stuff (vector<Sample*>& 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<AudioDiskstream> diskstream = audio_diskstream();
        
-       if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream.playlist())) == 0) {
+       if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(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<AudioPlaylist*>(new_playlist));
-       diskstream.set_record_enabled (false);
+       diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(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) {
 
index 982a7c5971cb0fa0c718444fd6e32a97d608aeb1..4a4659d1df9395124ce49651f6480cce11529162 100644 (file)
@@ -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<Ports> 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<Ports> 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<Ports> writer (ports);
+                       boost::shared_ptr<Ports> 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<Ports> writer (ports);
+                       boost::shared_ptr<Ports> 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<Ports> writer (ports);
+                               boost::shared_ptr<Ports> 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<Ports> 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<Ports> writer (ports);
+                               boost::shared_ptr<Ports> 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<Ports> p = ports.reader();
+
+               for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
                        jack_port_unregister (_jack, (*i)->_port);
                }
        }
 
-       ports.clear ();
+       {
+               RCUWriter<Ports> writer (ports);
+               boost::shared_ptr<Ports> 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<Ports> 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;
index e48f103b9fb976b57e7bebd512d0ddaddea41ea0..dc089794584024fe307ec1049ab65aa339319bab 100644 (file)
@@ -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 */
index b2d481077f227da9fa94451e7663d51a572dfcc5..151ff5bd3ef69dc2009da69c4b11b64d8e6da49d 100644 (file)
@@ -63,7 +63,6 @@ using namespace PBD;
  */
 jack_nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256;
 
-sigc::signal<void,Diskstream*>    Diskstream::DiskstreamCreated;
 sigc::signal<void,list<Source*>*> Diskstream::DeleteSources;
 sigc::signal<void>                Diskstream::DiskOverrun;
 sigc::signal<void>                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;
index b47981a47eff732c1025dd838eb33c368ec441c1..02c62eefa1d56032a33e2cbb6a3b745abff1316d 100644 (file)
@@ -111,7 +111,8 @@ Route::init ()
 
 Route::~Route ()
 {
-       GoingAway (); /* EMIT SIGNAL */
+       cerr << "deleting route " << _name << endl;
+
        clear_redirects (this);
 
        if (_control_outs) {
index 48f7fc30e9bec96b513fdb621977ed48289da8e5..378d4763bc6d02551a464719cba0dc7b1e384a1c 100644 (file)
@@ -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<RouteList> writer (routes);
+               boost::shared_ptr<RouteList> 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<DiskstreamList> dwriter (diskstreams);
+              boost::shared_ptr<DiskstreamList> 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<Diskstream> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<Sample*>::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<DiskstreamList> 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> route)
+Session::add_route (boost::shared_ptr<Route> route)
 {
        { 
                RCUWriter<RouteList> writer (routes);
@@ -1892,22 +1908,17 @@ Session::add_route (shared_ptr<Route> route)
 }
 
 void
-Session::add_diskstream (Diskstream* dstream)
+Session::add_diskstream (boost::shared_ptr<Diskstream> 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<DiskstreamList> writer (diskstreams);
+               boost::shared_ptr<DiskstreamList> 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> route)
 
        // FIXME: audio specific
        AudioTrack* at;
-       AudioDiskstream* ds = 0;
+       boost::shared_ptr<AudioDiskstream> ds;
        
        if ((at = dynamic_cast<AudioTrack*>(route.get())) != 0) {
-               ds = &at->audio_diskstream();
+               ds = at->audio_diskstream();
        }
        
        if (ds) {
 
                {
-                       Glib::RWLock::WriterLock lm (diskstream_lock);
-                       diskstreams.remove (ds);
+                       RCUWriter<DiskstreamList> dsl (diskstreams);
+                       boost::shared_ptr<DiskstreamList> d = dsl.get_copy();
+                       d->remove (ds);
                }
-
-               ds->unref ();
        }
 
        find_current_end ();
@@ -1983,7 +1991,9 @@ Session::remove_route (shared_ptr<Route> 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<DiskstreamList> 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<Diskstream>
 Session::diskstream_by_name (string name)
 {
-       Glib::RWLock::ReaderLock lm (diskstream_lock);
+       boost::shared_ptr<DiskstreamList> 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) {
-                       returni;
+                       return *i;
                }
        }
 
-       return 0;
+       return boost::shared_ptr<Diskstream>((Diskstream*) 0);
 }
 
-Diskstream *
+boost::shared_ptr<Diskstream>
 Session::diskstream_by_id (const PBD::ID& id)
 {
-       Glib::RWLock::ReaderLock lm (diskstream_lock);
+       boost::shared_ptr<DiskstreamList> 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>((Diskstream*) 0);
 }
 
 /* AudioRegion management */
@@ -2621,10 +2629,10 @@ int
 Session::remove_last_capture ()
 {
        list<Region*> r;
-
-       Glib::RWLock::ReaderLock lm (diskstream_lock);
        
-       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+       boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+       
+       for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
                list<Region*>& 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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 ();
 
index 6509a783bb8ad8481050480cea09241087001c81..5d691a7425c3a8ce5a3071d45d30690f362adbb4 100644 (file)
@@ -248,11 +248,11 @@ Session::butler_thread_work ()
 
                gettimeofday (&begin, 0);
 
-               Glib::RWLock::ReaderLock dsm (diskstream_lock);
+               boost::shared_ptr<DiskstreamList> 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<Diskstream> 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<DiskstreamList> dsl = diskstreams.reader();
+               for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
                        (*i)->set_pending_overwrite (true);
                }
        }
index b39c4f22185cb4398c181b3400420dd76d28f0b9..98653314b022cb02fc1d268c7e1b29fbd1616806 100644 (file)
@@ -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<DiskstreamList> 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)
index 88b111a1fbedb24fd8d1ea25b47065c2e60237b4..68ad11cf42d67ad9ad0fc64053d1aa9de6c4a057 100644 (file)
@@ -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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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;
                }
index 5a75c04b3f78f756765d34e2aa0c46974dc3be2d..6770428c65e8e22929ea62e84a6a1a1b721206f0 100644 (file)
@@ -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<AudioDiskstream> 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<DiskstreamList> dsl = diskstreams.reader();
+               for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
                        if (!(*i)->hidden()) {
                                child->add_child_nocopy ((*i)->get_state());
                        }
index 7c2b4f1c6f8502b44d2dea9f3c58e39462e918ab..8e0522c19d3e50cc347d361a9e6870c31c249d05 100644 (file)
@@ -192,8 +192,8 @@ Session::realtime_stop (bool abort)
 void
 Session::butler_transport_work ()
 {
-       Glib::RWLock::ReaderLock dsm (diskstream_lock);
        boost::shared_ptr<RouteList> r = routes.reader ();
+       boost::shared_ptr<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<DiskstreamList> 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<RouteList> 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<DiskstreamList> dsl = diskstreams.reader();
+
+       for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
                (*i)->set_capture_offset ();
        }
 }
index 58d8c1b3065692320e1a4ad3230a8458afe8871b..c8633d9e524c30437587c80e303fcb3aa190c8d5 100644 (file)
@@ -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
index 58a92a206a574e3e4066af422ff065cbfad304b8..e81db8ba8717108d9cb8dcf110bb2fee219c4a74 100644 (file)
@@ -5,8 +5,7 @@
 #include "glibmm/thread.h"
  
 #include <list> 
+
 template<class T>
 class RCUManager
 {
@@ -43,7 +42,7 @@ public:
  
        }
  
-       virtual boost::shared_ptr<T> write_copy ()
+       boost::shared_ptr<T> write_copy ()
        {
                m_lock.lock();
 
@@ -64,11 +63,11 @@ public:
                current_write_old = RCUManager<T>::m_rcu_value;
                
                boost::shared_ptr<T> new_copy (new T(**current_write_old));
-               
+
                return new_copy;
        }
  
-       virtual bool update (boost::shared_ptr<T> new_value)
+       bool update (boost::shared_ptr<T> 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;