remove recursive mutex from Playlist, replace with private regular mutex, force every...
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 1 May 2012 16:19:51 +0000 (16:19 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 1 May 2012 16:19:51 +0000 (16:19 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@12131 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/playlist.h
libs/ardour/audio_playlist.cc
libs/ardour/midi_playlist.cc
libs/ardour/playlist.cc

index 559a24062b60f691fc985c1a4eb1c6fc8916a538..9a76ec56ade89003d1432da26781c00f2e8b38a8 100644 (file)
@@ -39,6 +39,7 @@
 #include "pbd/stateful.h"
 #include "pbd/statefuldestructible.h"
 #include "pbd/sequence_property.h"
+#include "pbd/stacktrace.h"
 
 #include "evoral/types.hpp"
 
@@ -231,7 +232,10 @@ public:
   protected:
        struct RegionLock {
                RegionLock (Playlist *pl, bool do_block_notify = true) : playlist (pl), block_notify (do_block_notify) {
-                       playlist->region_lock.lock();
+                       if (!playlist->region_lock.trylock()) {
+                               std::cerr << "Lock for playlist " << pl->name() << " already held\n";
+                               PBD::stacktrace (std::cerr, 10);
+                       }       
                        if (block_notify) {
                                playlist->delay_notifications();
                        }
@@ -246,8 +250,6 @@ public:
                bool block_notify;
        };
 
-       friend class RegionLock;
-
        RegionListProperty   regions;  /* the current list of regions in the playlist */
        std::set<boost::shared_ptr<Region> > all_regions; /* all regions ever added to this playlist */
        PBD::ScopedConnectionList region_state_changed_connections;
@@ -255,11 +257,6 @@ public:
        int             _sort_id;
        mutable gint    block_notifications;
        mutable gint    ignore_state_changes;
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
-       mutable Glib::Threads::RecMutex region_lock;
-#else
-       mutable Glib::RecMutex region_lock;
-#endif 
        std::set<boost::shared_ptr<Region> > pending_adds;
        std::set<boost::shared_ptr<Region> > pending_removes;
        RegionList       pending_bounds;
@@ -303,6 +300,8 @@ public:
 
        void _set_sort_id ();
 
+       boost::shared_ptr<RegionList> regions_touched_locked (framepos_t start, framepos_t end);
+
        void notify_region_removed (boost::shared_ptr<Region>);
        void notify_region_added (boost::shared_ptr<Region>);
        void notify_layering_changed ();
@@ -365,8 +364,11 @@ public:
        */
        virtual void pre_uncombine (std::vector<boost::shared_ptr<Region> >&, boost::shared_ptr<Region>) {}
 
-private:
+  private:
+       friend class RegionLock;
+       mutable Glib::Mutex region_lock;
 
+  private:
        void setup_layering_indices (RegionList const &);
        void coalesce_and_check_crossfades (std::list<Evoral::Range<framepos_t> >);
        boost::shared_ptr<RegionList> find_regions_at (framepos_t);
index 9c304967dcfe64670800377a40ba6cdaf4170902..867f6f0ce422bd67886d82060d6d90dbedb11e21 100644 (file)
@@ -186,16 +186,12 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
           its OK to block (for short intervals).
        */
 
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
-       Glib::Threads::RecMutex::Lock lm (region_lock);
-#else  
-       Glib::RecMutex::Lock rm (region_lock);
-#endif 
+       Playlist::RegionLock rl (this, false);
 
        /* Find all the regions that are involved in the bit we are reading,
           and sort them by descending layer and ascending position.
        */
-       boost::shared_ptr<RegionList> all = regions_touched (start, start + cnt - 1);
+       boost::shared_ptr<RegionList> all = regions_touched_locked (start, start + cnt - 1);
        all->sort (ReadSorter ());
 
        /* This will be a list of the bits of our read range that we have
index 7e3d70bfe0915a32dc6aab5271adf9aefcabe8ce..81b14dd9337da6576377c9d461b179d03cbebcaa 100644 (file)
@@ -107,11 +107,8 @@ MidiPlaylist::read (Evoral::EventSink<framepos_t>& dst, framepos_t start, framec
           its OK to block (for short intervals).
        */
 
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
-       Glib::Threads::RecMutex::Lock rm (region_lock);
-#else  
-       Glib::RecMutex::Lock rm (region_lock);
-#endif 
+       Playlist::RegionLock rl (this, false);
+
        DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("++++++ %1 .. %2  +++++++ %3 trackers +++++++++++++++++\n", 
                                                            start, start + dur, _note_trackers.size()));
 
@@ -298,11 +295,8 @@ MidiPlaylist::read (Evoral::EventSink<framepos_t>& dst, framepos_t start, framec
 void
 MidiPlaylist::clear_note_trackers ()
 {
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
-       Glib::Threads::RecMutex::Lock rm (region_lock);
-#else  
-       Glib::RecMutex::Lock rm (region_lock);
-#endif 
+       Playlist::RegionLock rl (this, false);
+
        for (NoteTrackers::iterator n = _note_trackers.begin(); n != _note_trackers.end(); ++n) {
                delete n->second;
        }
@@ -407,12 +401,7 @@ MidiPlaylist::contained_automation()
           its OK to block (for short intervals).
        */
 
-#ifdef HAVE_GLIB_THREADS_RECMUTEX
-       Glib::Threads::RecMutex::Lock rm (region_lock);
-#else  
-       Glib::RecMutex::Lock rm (region_lock);
-#endif 
-
+       Playlist::RegionLock rl (this, false);
        set<Evoral::Parameter> ret;
 
        for (RegionList::const_iterator r = regions.begin(); r != regions.end(); ++r) {
index 076c4f27caec4c8867f6f7d1164b4251ec283da7..7be5d418f573b070b2d4b9286a42cbe5275c087b 100644 (file)
@@ -1758,6 +1758,12 @@ boost::shared_ptr<RegionList>
 Playlist::regions_touched (framepos_t start, framepos_t end)
 {
        RegionLock rlock (this);
+       return regions_touched_locked (start, end);
+}
+
+boost::shared_ptr<RegionList>
+Playlist::regions_touched_locked (framepos_t start, framepos_t end)
+{
        boost::shared_ptr<RegionList> rlist (new RegionList);
        
        for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
@@ -1769,126 +1775,125 @@ Playlist::regions_touched (framepos_t start, framepos_t end)
        return rlist;
 }
 
- framepos_t
- Playlist::find_next_transient (framepos_t from, int dir)
- {
-        RegionLock rlock (this);
-        AnalysisFeatureList points;
-        AnalysisFeatureList these_points;
-
-        for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-                if (dir > 0) {
-                        if ((*i)->last_frame() < from) {
-                                continue;
-                        }
-                } else {
-                        if ((*i)->first_frame() > from) {
-                                continue;
-                        }
-                }
-
-                (*i)->get_transients (these_points);
-
-                /* add first frame, just, err, because */
-
-                these_points.push_back ((*i)->first_frame());
-
-                points.insert (points.end(), these_points.begin(), these_points.end());
-                these_points.clear ();
-        }
-
-        if (points.empty()) {
-                return -1;
-        }
-
-        TransientDetector::cleanup_transients (points, _session.frame_rate(), 3.0);
-        bool reached = false;
-
-        if (dir > 0) {
-                for (AnalysisFeatureList::iterator x = points.begin(); x != points.end(); ++x) {
-                        if ((*x) >= from) {
-                                reached = true;
-                        }
-
-                        if (reached && (*x) > from) {
-                                return *x;
-                        }
-                }
-        } else {
-                for (AnalysisFeatureList::reverse_iterator x = points.rbegin(); x != points.rend(); ++x) {
-                        if ((*x) <= from) {
-                                reached = true;
-                        }
-
-                        if (reached && (*x) < from) {
-                                return *x;
-                        }
-                }
-        }
-
-        return -1;
- }
-
- boost::shared_ptr<Region>
- Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir)
- {
-        RegionLock rlock (this);
-        boost::shared_ptr<Region> ret;
-        framepos_t closest = max_framepos;
-
-        bool end_iter = false;
-
-        for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-
-                if(end_iter) break;
-
-                frameoffset_t distance;
-                boost::shared_ptr<Region> r = (*i);
-                framepos_t pos = 0;
-
-                switch (point) {
-                case Start:
-                        pos = r->first_frame ();
-                        break;
-                case End:
-                        pos = r->last_frame ();
-                        break;
-                case SyncPoint:
-                        pos = r->sync_position ();
-                        break;
-                }
-
-                switch (dir) {
-                case 1: /* forwards */
-
-                        if (pos > frame) {
-                                if ((distance = pos - frame) < closest) {
-                                        closest = distance;
-                                        ret = r;
-                                        end_iter = true;
-                                }
-                        }
-
-                        break;
-
-                default: /* backwards */
-
-                        if (pos < frame) {
-                                if ((distance = frame - pos) < closest) {
-                                        closest = distance;
-                                        ret = r;
-                                }
-                        }
-                        else {
-                                end_iter = true;
-                        }
-
-                        break;
-                }
-        }
+framepos_t
+Playlist::find_next_transient (framepos_t from, int dir)
+{
+       RegionLock rlock (this);
+       AnalysisFeatureList points;
+       AnalysisFeatureList these_points;
+       
+       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+               if (dir > 0) {
+                       if ((*i)->last_frame() < from) {
+                               continue;
+                       }
+               } else {
+                       if ((*i)->first_frame() > from) {
+                               continue;
+                       }
+               }
+               
+               (*i)->get_transients (these_points);
+               
+               /* add first frame, just, err, because */
+               
+               these_points.push_back ((*i)->first_frame());
+               
+               points.insert (points.end(), these_points.begin(), these_points.end());
+               these_points.clear ();
+       }
+       
+       if (points.empty()) {
+               return -1;
+       }
+       
+       TransientDetector::cleanup_transients (points, _session.frame_rate(), 3.0);
+       bool reached = false;
+       
+       if (dir > 0) {
+               for (AnalysisFeatureList::iterator x = points.begin(); x != points.end(); ++x) {
+                       if ((*x) >= from) {
+                               reached = true;
+                       }
+                       
+                       if (reached && (*x) > from) {
+                               return *x;
+                       }
+               }
+       } else {
+               for (AnalysisFeatureList::reverse_iterator x = points.rbegin(); x != points.rend(); ++x) {
+                       if ((*x) <= from) {
+                               reached = true;
+                       }
+                       
+                       if (reached && (*x) < from) {
+                               return *x;
+                       }
+               }
+       }
+       
+       return -1;
+}
 
-        return ret;
- }
+boost::shared_ptr<Region>
+Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir)
+{
+       RegionLock rlock (this);
+       boost::shared_ptr<Region> ret;
+       framepos_t closest = max_framepos;
+       
+       bool end_iter = false;
+       
+       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+               
+               if(end_iter) break;
+               
+               frameoffset_t distance;
+               boost::shared_ptr<Region> r = (*i);
+               framepos_t pos = 0;
+               
+               switch (point) {
+               case Start:
+                       pos = r->first_frame ();
+                       break;
+               case End:
+                       pos = r->last_frame ();
+                       break;
+               case SyncPoint:
+                       pos = r->sync_position ();
+                       break;
+               }
+               
+               switch (dir) {
+               case 1: /* forwards */
+                       
+                       if (pos > frame) {
+                               if ((distance = pos - frame) < closest) {
+                                       closest = distance;
+                                       ret = r;
+                                       end_iter = true;
+                               }
+                       }
+                       
+                       break;
+                       
+               default: /* backwards */
+                       
+                       if (pos < frame) {
+                               if ((distance = frame - pos) < closest) {
+                                       closest = distance;
+                                       ret = r;
+                               }
+                       } else {
+                               end_iter = true;
+                       }
+                       
+                       break;
+               }
+       }
+       
+       return ret;
+}
 
  framepos_t
  Playlist::find_next_region_boundary (framepos_t frame, int dir)