Commit b7af25cf authored by Sébastien Gonzalve's avatar Sébastien Gonzalve Committed by Arjan Spieard

Try to make locking more readable in loop

Relies on pattern UnlockGuard that boost names reverse_lock<> that
allows to unlock a mutex in a certain scope.
parent 5b6f8065
......@@ -151,32 +151,34 @@ AudioBuffer::AudioBuffer(fs::path const& file, unsigned int rate, size_t size):
auto ffmpeg = std::make_unique<AudioFFmpeg>(file, rate, std::ref(*this));
const_cast<double&>(m_duration) = ffmpeg->duration();
reader_thread = std::async(std::launch::async, [this, ffmpeg = std::move(ffmpeg)] {
std::unique_lock<std::mutex> l(m_mutex);
auto errors = 0u;
std::unique_lock<std::mutex> l(m_mutex);
while (!m_quit) {
if (m_seek_asked) {
auto seek_pos = m_read_pos / double(AV_TIME_BASE);
m_seek_asked = false;
m_write_pos = m_read_pos;
l.unlock();
auto seek_pos = m_read_pos / double(AV_TIME_BASE);
UnlockGuard<decltype(l)> unlocked(l); // release lock during seek
ffmpeg->seek(seek_pos);
} else
l.unlock();
continue;
}
try {
UnlockGuard<decltype(l)> unlocked(l); // release lock during possibly blocking ffmpeg stuff
ffmpeg->handleOneFrame();
errors = 0;
l.lock();
} catch (const FFmpeg::Eof&) {
l.lock();
// now we know exact eof_pos
m_eof_pos = m_write_pos;
// Wait here on eof: either quit is asked, either a new seek
// was asked and return back reading frames
m_cond.wait(l, [this]{ return m_quit || m_seek_asked; });
} catch (const std::exception& e) {
UnlockGuard<decltype(l)> unlocked(l); // unlock while doing IOs
std::clog << "ffmpeg/error: " << e.what() << std::endl;
if (++errors > 2) std::clog << "ffmpeg/error: FFMPEG terminating due to multiple errors" << std::endl;
l.lock();
}
}
});
......
......@@ -35,3 +35,17 @@ template <typename T> T smoothstep(T edge0, T edge1, T x) {
/** Convenience smoothstep wrapper with edges at 0 and 1 **/
template <typename T> T smoothstep(T x) { return smoothstep<T>(0, 1, x); }
/** Symetric of lock_guard: release a lock in constructor and take it back in destructor */
template <class Lockable>
struct UnlockGuard {
UnlockGuard(Lockable& m) : m_mutex(m) { m_mutex.unlock(); }
~UnlockGuard() { m_mutex.lock(); }
UnlockGuard(const UnlockGuard&) = delete;
UnlockGuard& operator=(const UnlockGuard&) = delete;
private:
Lockable& m_mutex;
};
......@@ -58,24 +58,27 @@ Video::Video(fs::path const& _videoFile, double videoGap): m_videoGap(videoGap),
auto seek_pos = m_readPosition;
// discard all outdated frame. To avoid races between clean and push, clean and push are done in this thread.
m_queue.clear();
l.unlock();
UnlockGuard<decltype(l)> unlocked(l); // release lock during seek
ffmpeg->seek(seek_pos);
continue;
}
else l.unlock();
try {
UnlockGuard<decltype(l)> unlocked(l); // release lock during possibly blocking ffmpeg stuff
ffmpeg->handleOneFrame();
errors = 0;
l.lock();
errors = 0;
} catch (FFmpeg::Eof&) {
push(Bitmap());
std::clog << "ffmpeg/debug: done loading " << file << std::endl;
l.lock();
m_cond.wait(l, [this]{ return m_quit || m_seek_asked; });
{
UnlockGuard<decltype(l)> unlocked(l); // release lock for possibly blocking calls
push(Bitmap()); // EOF marker
std::clog << "ffmpeg/debug: done loading " << file << std::endl;
}
m_cond.wait(l, [this]{ return m_quit || m_seek_asked; });
} catch (std::exception& e) {
UnlockGuard<decltype(l)> unlocked(l); // release lock for possibly blocking calls
std::clog << "ffmpeg/error: " << file << ": " << e.what() << std::endl;
if (++errors > 2) { std::clog << "ffmpeg/error: FFMPEG terminating due to multiple errors" << std::endl; break; }
l.lock();
}
}
});
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment