remove recursive mutex from Playlist, replace with private regular mutex, force everyone to use Playlist::RegionLock to allow checking on lock handling if necessary; fix recursive use of lock in AudioPlaylist::read()
git-svn-id: svn://localhost/ardour2/branches/3.0@12131 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
77be4a2742
commit
ac46e5edb4
|
@ -39,6 +39,7 @@
|
||||||
#include "pbd/stateful.h"
|
#include "pbd/stateful.h"
|
||||||
#include "pbd/statefuldestructible.h"
|
#include "pbd/statefuldestructible.h"
|
||||||
#include "pbd/sequence_property.h"
|
#include "pbd/sequence_property.h"
|
||||||
|
#include "pbd/stacktrace.h"
|
||||||
|
|
||||||
#include "evoral/types.hpp"
|
#include "evoral/types.hpp"
|
||||||
|
|
||||||
|
@ -231,7 +232,10 @@ public:
|
||||||
protected:
|
protected:
|
||||||
struct RegionLock {
|
struct RegionLock {
|
||||||
RegionLock (Playlist *pl, bool do_block_notify = true) : playlist (pl), block_notify (do_block_notify) {
|
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) {
|
if (block_notify) {
|
||||||
playlist->delay_notifications();
|
playlist->delay_notifications();
|
||||||
}
|
}
|
||||||
|
@ -246,8 +250,6 @@ public:
|
||||||
bool block_notify;
|
bool block_notify;
|
||||||
};
|
};
|
||||||
|
|
||||||
friend class RegionLock;
|
|
||||||
|
|
||||||
RegionListProperty regions; /* the current list of regions in the playlist */
|
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 */
|
std::set<boost::shared_ptr<Region> > all_regions; /* all regions ever added to this playlist */
|
||||||
PBD::ScopedConnectionList region_state_changed_connections;
|
PBD::ScopedConnectionList region_state_changed_connections;
|
||||||
|
@ -255,11 +257,6 @@ public:
|
||||||
int _sort_id;
|
int _sort_id;
|
||||||
mutable gint block_notifications;
|
mutable gint block_notifications;
|
||||||
mutable gint ignore_state_changes;
|
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_adds;
|
||||||
std::set<boost::shared_ptr<Region> > pending_removes;
|
std::set<boost::shared_ptr<Region> > pending_removes;
|
||||||
RegionList pending_bounds;
|
RegionList pending_bounds;
|
||||||
|
@ -303,6 +300,8 @@ public:
|
||||||
|
|
||||||
void _set_sort_id ();
|
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_removed (boost::shared_ptr<Region>);
|
||||||
void notify_region_added (boost::shared_ptr<Region>);
|
void notify_region_added (boost::shared_ptr<Region>);
|
||||||
void notify_layering_changed ();
|
void notify_layering_changed ();
|
||||||
|
@ -365,8 +364,11 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void pre_uncombine (std::vector<boost::shared_ptr<Region> >&, boost::shared_ptr<Region>) {}
|
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 setup_layering_indices (RegionList const &);
|
||||||
void coalesce_and_check_crossfades (std::list<Evoral::Range<framepos_t> >);
|
void coalesce_and_check_crossfades (std::list<Evoral::Range<framepos_t> >);
|
||||||
boost::shared_ptr<RegionList> find_regions_at (framepos_t);
|
boost::shared_ptr<RegionList> find_regions_at (framepos_t);
|
||||||
|
|
|
@ -186,16 +186,12 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
|
||||||
its OK to block (for short intervals).
|
its OK to block (for short intervals).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_GLIB_THREADS_RECMUTEX
|
Playlist::RegionLock rl (this, false);
|
||||||
Glib::Threads::RecMutex::Lock lm (region_lock);
|
|
||||||
#else
|
|
||||||
Glib::RecMutex::Lock rm (region_lock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Find all the regions that are involved in the bit we are reading,
|
/* Find all the regions that are involved in the bit we are reading,
|
||||||
and sort them by descending layer and ascending position.
|
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 ());
|
all->sort (ReadSorter ());
|
||||||
|
|
||||||
/* This will be a list of the bits of our read range that we have
|
/* This will be a list of the bits of our read range that we have
|
||||||
|
|
|
@ -107,11 +107,8 @@ MidiPlaylist::read (Evoral::EventSink<framepos_t>& dst, framepos_t start, framec
|
||||||
its OK to block (for short intervals).
|
its OK to block (for short intervals).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_GLIB_THREADS_RECMUTEX
|
Playlist::RegionLock rl (this, false);
|
||||||
Glib::Threads::RecMutex::Lock rm (region_lock);
|
|
||||||
#else
|
|
||||||
Glib::RecMutex::Lock rm (region_lock);
|
|
||||||
#endif
|
|
||||||
DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("++++++ %1 .. %2 +++++++ %3 trackers +++++++++++++++++\n",
|
DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("++++++ %1 .. %2 +++++++ %3 trackers +++++++++++++++++\n",
|
||||||
start, start + dur, _note_trackers.size()));
|
start, start + dur, _note_trackers.size()));
|
||||||
|
|
||||||
|
@ -298,11 +295,8 @@ MidiPlaylist::read (Evoral::EventSink<framepos_t>& dst, framepos_t start, framec
|
||||||
void
|
void
|
||||||
MidiPlaylist::clear_note_trackers ()
|
MidiPlaylist::clear_note_trackers ()
|
||||||
{
|
{
|
||||||
#ifdef HAVE_GLIB_THREADS_RECMUTEX
|
Playlist::RegionLock rl (this, false);
|
||||||
Glib::Threads::RecMutex::Lock rm (region_lock);
|
|
||||||
#else
|
|
||||||
Glib::RecMutex::Lock rm (region_lock);
|
|
||||||
#endif
|
|
||||||
for (NoteTrackers::iterator n = _note_trackers.begin(); n != _note_trackers.end(); ++n) {
|
for (NoteTrackers::iterator n = _note_trackers.begin(); n != _note_trackers.end(); ++n) {
|
||||||
delete n->second;
|
delete n->second;
|
||||||
}
|
}
|
||||||
|
@ -407,12 +401,7 @@ MidiPlaylist::contained_automation()
|
||||||
its OK to block (for short intervals).
|
its OK to block (for short intervals).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_GLIB_THREADS_RECMUTEX
|
Playlist::RegionLock rl (this, false);
|
||||||
Glib::Threads::RecMutex::Lock rm (region_lock);
|
|
||||||
#else
|
|
||||||
Glib::RecMutex::Lock rm (region_lock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
set<Evoral::Parameter> ret;
|
set<Evoral::Parameter> ret;
|
||||||
|
|
||||||
for (RegionList::const_iterator r = regions.begin(); r != regions.end(); ++r) {
|
for (RegionList::const_iterator r = regions.begin(); r != regions.end(); ++r) {
|
||||||
|
|
|
@ -1758,6 +1758,12 @@ boost::shared_ptr<RegionList>
|
||||||
Playlist::regions_touched (framepos_t start, framepos_t end)
|
Playlist::regions_touched (framepos_t start, framepos_t end)
|
||||||
{
|
{
|
||||||
RegionLock rlock (this);
|
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);
|
boost::shared_ptr<RegionList> rlist (new RegionList);
|
||||||
|
|
||||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
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;
|
return rlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
framepos_t
|
framepos_t
|
||||||
Playlist::find_next_transient (framepos_t from, int dir)
|
Playlist::find_next_transient (framepos_t from, int dir)
|
||||||
{
|
{
|
||||||
RegionLock rlock (this);
|
RegionLock rlock (this);
|
||||||
AnalysisFeatureList points;
|
AnalysisFeatureList points;
|
||||||
AnalysisFeatureList these_points;
|
AnalysisFeatureList these_points;
|
||||||
|
|
||||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||||
if (dir > 0) {
|
if (dir > 0) {
|
||||||
if ((*i)->last_frame() < from) {
|
if ((*i)->last_frame() < from) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((*i)->first_frame() > from) {
|
if ((*i)->first_frame() > from) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(*i)->get_transients (these_points);
|
(*i)->get_transients (these_points);
|
||||||
|
|
||||||
/* add first frame, just, err, because */
|
/* add first frame, just, err, because */
|
||||||
|
|
||||||
these_points.push_back ((*i)->first_frame());
|
these_points.push_back ((*i)->first_frame());
|
||||||
|
|
||||||
points.insert (points.end(), these_points.begin(), these_points.end());
|
points.insert (points.end(), these_points.begin(), these_points.end());
|
||||||
these_points.clear ();
|
these_points.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (points.empty()) {
|
if (points.empty()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransientDetector::cleanup_transients (points, _session.frame_rate(), 3.0);
|
TransientDetector::cleanup_transients (points, _session.frame_rate(), 3.0);
|
||||||
bool reached = false;
|
bool reached = false;
|
||||||
|
|
||||||
if (dir > 0) {
|
if (dir > 0) {
|
||||||
for (AnalysisFeatureList::iterator x = points.begin(); x != points.end(); ++x) {
|
for (AnalysisFeatureList::iterator x = points.begin(); x != points.end(); ++x) {
|
||||||
if ((*x) >= from) {
|
if ((*x) >= from) {
|
||||||
reached = true;
|
reached = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reached && (*x) > from) {
|
if (reached && (*x) > from) {
|
||||||
return *x;
|
return *x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (AnalysisFeatureList::reverse_iterator x = points.rbegin(); x != points.rend(); ++x) {
|
for (AnalysisFeatureList::reverse_iterator x = points.rbegin(); x != points.rend(); ++x) {
|
||||||
if ((*x) <= from) {
|
if ((*x) <= from) {
|
||||||
reached = true;
|
reached = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reached && (*x) < from) {
|
if (reached && (*x) < from) {
|
||||||
return *x;
|
return *x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Region>
|
boost::shared_ptr<Region>
|
||||||
Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir)
|
Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir)
|
||||||
{
|
{
|
||||||
RegionLock rlock (this);
|
RegionLock rlock (this);
|
||||||
boost::shared_ptr<Region> ret;
|
boost::shared_ptr<Region> ret;
|
||||||
framepos_t closest = max_framepos;
|
framepos_t closest = max_framepos;
|
||||||
|
|
||||||
bool end_iter = false;
|
bool end_iter = false;
|
||||||
|
|
||||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||||
|
|
||||||
if(end_iter) break;
|
if(end_iter) break;
|
||||||
|
|
||||||
frameoffset_t distance;
|
frameoffset_t distance;
|
||||||
boost::shared_ptr<Region> r = (*i);
|
boost::shared_ptr<Region> r = (*i);
|
||||||
framepos_t pos = 0;
|
framepos_t pos = 0;
|
||||||
|
|
||||||
switch (point) {
|
switch (point) {
|
||||||
case Start:
|
case Start:
|
||||||
pos = r->first_frame ();
|
pos = r->first_frame ();
|
||||||
break;
|
break;
|
||||||
case End:
|
case End:
|
||||||
pos = r->last_frame ();
|
pos = r->last_frame ();
|
||||||
break;
|
break;
|
||||||
case SyncPoint:
|
case SyncPoint:
|
||||||
pos = r->sync_position ();
|
pos = r->sync_position ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case 1: /* forwards */
|
case 1: /* forwards */
|
||||||
|
|
||||||
if (pos > frame) {
|
if (pos > frame) {
|
||||||
if ((distance = pos - frame) < closest) {
|
if ((distance = pos - frame) < closest) {
|
||||||
closest = distance;
|
closest = distance;
|
||||||
ret = r;
|
ret = r;
|
||||||
end_iter = true;
|
end_iter = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* backwards */
|
default: /* backwards */
|
||||||
|
|
||||||
if (pos < frame) {
|
if (pos < frame) {
|
||||||
if ((distance = frame - pos) < closest) {
|
if ((distance = frame - pos) < closest) {
|
||||||
closest = distance;
|
closest = distance;
|
||||||
ret = r;
|
ret = r;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
end_iter = true;
|
||||||
end_iter = true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
framepos_t
|
framepos_t
|
||||||
Playlist::find_next_region_boundary (framepos_t frame, int dir)
|
Playlist::find_next_region_boundary (framepos_t frame, int dir)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user