input/InputStreams: pass std::unique_lock<> to various methods
This commit is contained in:
parent
040573c636
commit
1b5c1f75a4
@ -72,7 +72,8 @@ public:
|
||||
|
||||
/* virtual methods from InputStream */
|
||||
bool IsEOF() noexcept override;
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
|
||||
private:
|
||||
void Open();
|
||||
@ -147,7 +148,7 @@ Bzip2InputStream::FillBuffer()
|
||||
}
|
||||
|
||||
size_t
|
||||
Bzip2InputStream::Read(void *ptr, size_t length)
|
||||
Bzip2InputStream::Read(std::unique_lock<Mutex> &, void *ptr, size_t length)
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
|
||||
|
@ -157,7 +157,8 @@ public:
|
||||
|
||||
/* virtual methods from InputStream */
|
||||
bool IsEOF() noexcept override;
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
};
|
||||
|
||||
InputStreamPtr
|
||||
@ -174,7 +175,8 @@ Iso9660ArchiveFile::OpenStream(const char *pathname,
|
||||
}
|
||||
|
||||
size_t
|
||||
Iso9660InputStream::Read(void *ptr, size_t read_size)
|
||||
Iso9660InputStream::Read(std::unique_lock<Mutex> &,
|
||||
void *ptr, size_t read_size)
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
|
||||
|
@ -111,8 +111,9 @@ public:
|
||||
|
||||
/* virtual methods from InputStream */
|
||||
bool IsEOF() noexcept override;
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
void Seek(offset_type offset) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
void Seek(std::unique_lock<Mutex> &lock, offset_type offset) override;
|
||||
};
|
||||
|
||||
InputStreamPtr
|
||||
@ -130,7 +131,7 @@ ZzipArchiveFile::OpenStream(const char *pathname,
|
||||
}
|
||||
|
||||
size_t
|
||||
ZzipInputStream::Read(void *ptr, size_t read_size)
|
||||
ZzipInputStream::Read(std::unique_lock<Mutex> &, void *ptr, size_t read_size)
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
|
||||
@ -149,7 +150,7 @@ ZzipInputStream::IsEOF() noexcept
|
||||
}
|
||||
|
||||
void
|
||||
ZzipInputStream::Seek(offset_type new_offset)
|
||||
ZzipInputStream::Seek(std::unique_lock<Mutex> &, offset_type new_offset)
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
|
||||
|
@ -292,9 +292,9 @@ read_stream_art(Response &r, const char *uri, size_t offset)
|
||||
size_t read_size;
|
||||
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
is->Seek(offset);
|
||||
read_size = is->Read(&buffer, CHUNK_SIZE);
|
||||
std::unique_lock<Mutex> lock(mutex);
|
||||
is->Seek(lock, offset);
|
||||
read_size = is->Read(lock, &buffer, CHUNK_SIZE);
|
||||
}
|
||||
|
||||
r.Format("size: %" PRIoffset "\n"
|
||||
|
@ -305,7 +305,7 @@ GetChromaprintCommand::Read(InputStream &is, void *buffer, size_t length)
|
||||
cond.wait(lock);
|
||||
}
|
||||
|
||||
return is.Read(buffer, length);
|
||||
return is.Read(lock, buffer, length);
|
||||
}
|
||||
|
||||
CommandResult
|
||||
|
@ -403,7 +403,7 @@ try {
|
||||
dc.cond.wait(lock);
|
||||
}
|
||||
|
||||
size_t nbytes = is.Read(buffer, length);
|
||||
size_t nbytes = is.Read(lock, buffer, length);
|
||||
assert(nbytes > 0 || is.IsEOF());
|
||||
|
||||
return nbytes;
|
||||
|
@ -55,7 +55,8 @@ static constexpr Domain decoder_thread_domain("decoder_thread");
|
||||
static bool
|
||||
decoder_stream_decode(const DecoderPlugin &plugin,
|
||||
DecoderBridge &bridge,
|
||||
InputStream &input_stream)
|
||||
InputStream &input_stream,
|
||||
std::unique_lock<Mutex> &lock)
|
||||
{
|
||||
assert(plugin.stream_decode != nullptr);
|
||||
assert(bridge.stream_tag == nullptr);
|
||||
@ -70,7 +71,7 @@ decoder_stream_decode(const DecoderPlugin &plugin,
|
||||
|
||||
/* rewind the stream, so each plugin gets a fresh start */
|
||||
try {
|
||||
input_stream.Rewind();
|
||||
input_stream.Rewind(lock);
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
@ -161,6 +162,7 @@ decoder_check_plugin(const DecoderPlugin &plugin, const InputStream &is,
|
||||
|
||||
static bool
|
||||
decoder_run_stream_plugin(DecoderBridge &bridge, InputStream &is,
|
||||
std::unique_lock<Mutex> &lock,
|
||||
const char *suffix,
|
||||
const DecoderPlugin &plugin,
|
||||
bool &tried_r)
|
||||
@ -171,11 +173,12 @@ decoder_run_stream_plugin(DecoderBridge &bridge, InputStream &is,
|
||||
bridge.Reset();
|
||||
|
||||
tried_r = true;
|
||||
return decoder_stream_decode(plugin, bridge, is);
|
||||
return decoder_stream_decode(plugin, bridge, is, lock);
|
||||
}
|
||||
|
||||
static bool
|
||||
decoder_run_stream_locked(DecoderBridge &bridge, InputStream &is,
|
||||
std::unique_lock<Mutex> &lock,
|
||||
const char *uri, bool &tried_r)
|
||||
{
|
||||
UriSuffixBuffer suffix_buffer;
|
||||
@ -183,7 +186,8 @@ decoder_run_stream_locked(DecoderBridge &bridge, InputStream &is,
|
||||
|
||||
using namespace std::placeholders;
|
||||
const auto f = std::bind(decoder_run_stream_plugin,
|
||||
std::ref(bridge), std::ref(is), suffix,
|
||||
std::ref(bridge), std::ref(is), std::ref(lock),
|
||||
suffix,
|
||||
_1, std::ref(tried_r));
|
||||
return decoder_plugins_try(f);
|
||||
}
|
||||
@ -192,7 +196,8 @@ decoder_run_stream_locked(DecoderBridge &bridge, InputStream &is,
|
||||
* Try decoding a stream, using the fallback plugin.
|
||||
*/
|
||||
static bool
|
||||
decoder_run_stream_fallback(DecoderBridge &bridge, InputStream &is)
|
||||
decoder_run_stream_fallback(DecoderBridge &bridge, InputStream &is,
|
||||
std::unique_lock<Mutex> &lock)
|
||||
{
|
||||
const struct DecoderPlugin *plugin;
|
||||
|
||||
@ -202,7 +207,7 @@ decoder_run_stream_fallback(DecoderBridge &bridge, InputStream &is)
|
||||
plugin = decoder_plugin_from_name("mad");
|
||||
#endif
|
||||
return plugin != nullptr && plugin->stream_decode != nullptr &&
|
||||
decoder_stream_decode(*plugin, bridge, is);
|
||||
decoder_stream_decode(*plugin, bridge, is, lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -249,16 +254,16 @@ decoder_run_stream(DecoderBridge &bridge, const char *uri)
|
||||
|
||||
MaybeLoadReplayGain(bridge, *input_stream);
|
||||
|
||||
const std::lock_guard<Mutex> protect(dc.mutex);
|
||||
std::unique_lock<Mutex> lock(dc.mutex);
|
||||
|
||||
bool tried = false;
|
||||
return dc.command == DecoderCommand::STOP ||
|
||||
decoder_run_stream_locked(bridge, *input_stream, uri,
|
||||
decoder_run_stream_locked(bridge, *input_stream, lock, uri,
|
||||
tried) ||
|
||||
/* fallback to mp3: this is needed for bastard streams
|
||||
that don't have a suffix or set the mimeType */
|
||||
(!tried &&
|
||||
decoder_run_stream_fallback(bridge, *input_stream));
|
||||
decoder_run_stream_fallback(bridge, *input_stream, lock));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,8 +287,9 @@ TryDecoderFile(DecoderBridge &bridge, Path path_fs, const char *suffix,
|
||||
const std::lock_guard<Mutex> protect(dc.mutex);
|
||||
return decoder_file_decode(plugin, bridge, path_fs);
|
||||
} else if (plugin.stream_decode != nullptr) {
|
||||
const std::lock_guard<Mutex> protect(dc.mutex);
|
||||
return decoder_stream_decode(plugin, bridge, input_stream);
|
||||
std::unique_lock<Mutex> lock(dc.mutex);
|
||||
return decoder_stream_decode(plugin, bridge, input_stream,
|
||||
lock);
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
@ -95,7 +95,8 @@ AsyncInputStream::IsEOF() noexcept
|
||||
}
|
||||
|
||||
void
|
||||
AsyncInputStream::Seek(offset_type new_offset)
|
||||
AsyncInputStream::Seek(std::unique_lock<Mutex> &lock,
|
||||
offset_type new_offset)
|
||||
{
|
||||
assert(IsReady());
|
||||
assert(seek_state == SeekState::NONE);
|
||||
@ -136,7 +137,7 @@ AsyncInputStream::Seek(offset_type new_offset)
|
||||
CondInputStreamHandler cond_handler;
|
||||
const ScopeExchangeInputStreamHandler h(*this, &cond_handler);
|
||||
while (seek_state != SeekState::NONE)
|
||||
cond_handler.cond.wait(mutex);
|
||||
cond_handler.cond.wait(lock);
|
||||
|
||||
Check();
|
||||
}
|
||||
@ -171,7 +172,8 @@ AsyncInputStream::IsAvailable() noexcept
|
||||
}
|
||||
|
||||
size_t
|
||||
AsyncInputStream::Read(void *ptr, size_t read_size)
|
||||
AsyncInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t read_size)
|
||||
{
|
||||
assert(!GetEventLoop().IsInside());
|
||||
|
||||
@ -187,7 +189,7 @@ AsyncInputStream::Read(void *ptr, size_t read_size)
|
||||
break;
|
||||
|
||||
const ScopeExchangeInputStreamHandler h(*this, &cond_handler);
|
||||
cond_handler.cond.wait(mutex);
|
||||
cond_handler.cond.wait(lock);
|
||||
}
|
||||
|
||||
const size_t nbytes = std::min(read_size, r.size);
|
||||
|
@ -83,10 +83,12 @@ public:
|
||||
/* virtual methods from InputStream */
|
||||
void Check() final;
|
||||
bool IsEOF() noexcept final;
|
||||
void Seek(offset_type new_offset) final;
|
||||
void Seek(std::unique_lock<Mutex> &lock,
|
||||
offset_type new_offset) final;
|
||||
std::unique_ptr<Tag> ReadTag() noexcept final;
|
||||
bool IsAvailable() noexcept final;
|
||||
size_t Read(void *ptr, size_t read_size) final;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t read_size) final;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -64,7 +64,8 @@ BufferedInputStream::Check()
|
||||
}
|
||||
|
||||
void
|
||||
BufferedInputStream::Seek(offset_type new_offset)
|
||||
BufferedInputStream::Seek(std::unique_lock<Mutex> &lock,
|
||||
offset_type new_offset)
|
||||
{
|
||||
if (new_offset >= size) {
|
||||
offset = size;
|
||||
@ -84,7 +85,7 @@ BufferedInputStream::Seek(offset_type new_offset)
|
||||
wake_cond.notify_one();
|
||||
|
||||
while (seek)
|
||||
client_cond.wait(mutex);
|
||||
client_cond.wait(lock);
|
||||
|
||||
if (seek_error)
|
||||
std::rethrow_exception(std::exchange(seek_error, {}));
|
||||
@ -105,7 +106,8 @@ BufferedInputStream::IsAvailable() noexcept
|
||||
}
|
||||
|
||||
size_t
|
||||
BufferedInputStream::Read(void *ptr, size_t s)
|
||||
BufferedInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t s)
|
||||
{
|
||||
if (offset >= size)
|
||||
return 0;
|
||||
@ -140,7 +142,7 @@ BufferedInputStream::Read(void *ptr, size_t s)
|
||||
wake_cond.notify_one();
|
||||
}
|
||||
|
||||
client_cond.wait(mutex);
|
||||
client_cond.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +158,7 @@ BufferedInputStream::RunThread() noexcept
|
||||
|
||||
if (seek) {
|
||||
try {
|
||||
input->Seek(seek_offset);
|
||||
input->Seek(lock, seek_offset);
|
||||
} catch (...) {
|
||||
seek_error = std::current_exception();
|
||||
}
|
||||
@ -183,7 +185,7 @@ BufferedInputStream::RunThread() noexcept
|
||||
offset to prepare filling
|
||||
the buffer from there */
|
||||
try {
|
||||
input->Seek(offset);
|
||||
input->Seek(lock, offset);
|
||||
} catch (...) {
|
||||
read_error = std::current_exception();
|
||||
client_cond.notify_one();
|
||||
@ -195,7 +197,8 @@ BufferedInputStream::RunThread() noexcept
|
||||
}
|
||||
|
||||
try {
|
||||
size_t nbytes = input->Read(w.data, w.size);
|
||||
size_t nbytes = input->Read(lock,
|
||||
w.data, w.size);
|
||||
buffer.Commit(read_offset,
|
||||
read_offset + nbytes);
|
||||
} catch (...) {
|
||||
|
@ -85,12 +85,13 @@ public:
|
||||
/* we don't need to implement Update() because all attributes
|
||||
have been copied already in our constructor */
|
||||
//void Update() noexcept;
|
||||
void Seek(offset_type offset) override;
|
||||
void Seek(std::unique_lock<Mutex> &lock, offset_type offset) override;
|
||||
bool IsEOF() noexcept override;
|
||||
/* we don't support tags */
|
||||
// std::unique_ptr<Tag> ReadTag() override;
|
||||
bool IsAvailable() noexcept override;
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
|
||||
/* virtual methods from class InputStreamHandler */
|
||||
void OnInputStreamReady() noexcept override {
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
std::rethrow_exception(error);
|
||||
}
|
||||
|
||||
void Seek(offset_type) override {
|
||||
void Seek(std::unique_lock<Mutex> &, offset_type) override {
|
||||
std::rethrow_exception(error);
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t Read(void *, size_t) override {
|
||||
size_t Read(std::unique_lock<Mutex> &, void *, size_t) override {
|
||||
std::rethrow_exception(error);
|
||||
}
|
||||
};
|
||||
|
@ -80,13 +80,14 @@ IcyInputStream::ReadTag() noexcept
|
||||
}
|
||||
|
||||
size_t
|
||||
IcyInputStream::Read(void *ptr, size_t read_size)
|
||||
IcyInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t read_size)
|
||||
{
|
||||
if (!IsEnabled())
|
||||
return ProxyInputStream::Read(ptr, read_size);
|
||||
return ProxyInputStream::Read(lock, ptr, read_size);
|
||||
|
||||
while (true) {
|
||||
size_t nbytes = ProxyInputStream::Read(ptr, read_size);
|
||||
size_t nbytes = ProxyInputStream::Read(lock, ptr, read_size);
|
||||
if (nbytes == 0)
|
||||
return 0;
|
||||
|
||||
|
@ -66,7 +66,8 @@ public:
|
||||
/* virtual methods from InputStream */
|
||||
void Update() noexcept override;
|
||||
std::unique_ptr<Tag> ReadTag() noexcept override;
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -72,7 +72,7 @@ InputStream::CheapSeeking() const noexcept
|
||||
}
|
||||
|
||||
void
|
||||
InputStream::Seek(gcc_unused offset_type new_offset)
|
||||
InputStream::Seek(std::unique_lock<Mutex> &, gcc_unused offset_type new_offset)
|
||||
{
|
||||
throw std::runtime_error("Seeking is not implemented");
|
||||
}
|
||||
@ -80,15 +80,15 @@ InputStream::Seek(gcc_unused offset_type new_offset)
|
||||
void
|
||||
InputStream::LockSeek(offset_type _offset)
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
Seek(_offset);
|
||||
std::unique_lock<Mutex> lock(mutex);
|
||||
Seek(lock, _offset);
|
||||
}
|
||||
|
||||
void
|
||||
InputStream::LockSkip(offset_type _offset)
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
Skip(_offset);
|
||||
std::unique_lock<Mutex> lock(mutex);
|
||||
Skip(lock, _offset);
|
||||
}
|
||||
|
||||
std::unique_ptr<Tag>
|
||||
@ -119,18 +119,18 @@ InputStream::LockRead(void *ptr, size_t _size)
|
||||
#endif
|
||||
assert(_size > 0);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
return Read(ptr, _size);
|
||||
std::unique_lock<Mutex> lock(mutex);
|
||||
return Read(lock, ptr, _size);
|
||||
}
|
||||
|
||||
void
|
||||
InputStream::ReadFull(void *_ptr, size_t _size)
|
||||
InputStream::ReadFull(std::unique_lock<Mutex> &lock, void *_ptr, size_t _size)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *)_ptr;
|
||||
|
||||
size_t nbytes_total = 0;
|
||||
while (_size > 0) {
|
||||
size_t nbytes = Read(ptr + nbytes_total, _size);
|
||||
size_t nbytes = Read(lock, ptr + nbytes_total, _size);
|
||||
if (nbytes == 0)
|
||||
throw std::runtime_error("Unexpected end of file");
|
||||
|
||||
@ -148,8 +148,8 @@ InputStream::LockReadFull(void *ptr, size_t _size)
|
||||
#endif
|
||||
assert(_size > 0);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
ReadFull(ptr, _size);
|
||||
std::unique_lock<Mutex> lock(mutex);
|
||||
ReadFull(lock, ptr, _size);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -271,9 +271,11 @@ public:
|
||||
*
|
||||
* Throws std::runtime_error on error.
|
||||
*
|
||||
* @param lock the locked mutex; may be used to wait on
|
||||
* condition variables
|
||||
* @param offset the relative offset
|
||||
*/
|
||||
virtual void Seek(offset_type offset);
|
||||
virtual void Seek(std::unique_lock<Mutex> &lock, offset_type offset);
|
||||
|
||||
/**
|
||||
* Wrapper for Seek() which locks and unlocks the mutex; the
|
||||
@ -285,8 +287,8 @@ public:
|
||||
* Rewind to the beginning of the stream. This is a wrapper
|
||||
* for Seek(0, error).
|
||||
*/
|
||||
void Rewind() {
|
||||
Seek(0);
|
||||
void Rewind(std::unique_lock<Mutex> &lock) {
|
||||
Seek(lock, 0);
|
||||
}
|
||||
|
||||
void LockRewind() {
|
||||
@ -296,8 +298,9 @@ public:
|
||||
/**
|
||||
* Skip input bytes.
|
||||
*/
|
||||
void Skip(offset_type _offset) {
|
||||
Seek(GetOffset() + _offset);
|
||||
void Skip(std::unique_lock<Mutex> &lock,
|
||||
offset_type _offset) {
|
||||
Seek(lock, GetOffset() + _offset);
|
||||
}
|
||||
|
||||
void LockSkip(offset_type _offset);
|
||||
@ -351,12 +354,15 @@ public:
|
||||
*
|
||||
* Throws std::runtime_error on error.
|
||||
*
|
||||
* @param lock the locked mutex; may be used to wait on
|
||||
* condition variables
|
||||
* @param ptr the buffer to read into
|
||||
* @param size the maximum number of bytes to read
|
||||
* @return the number of bytes read
|
||||
*/
|
||||
gcc_nonnull_all
|
||||
virtual size_t Read(void *ptr, size_t size) = 0;
|
||||
virtual size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) = 0;
|
||||
|
||||
/**
|
||||
* Wrapper for Read() which locks and unlocks the mutex;
|
||||
@ -379,7 +385,7 @@ public:
|
||||
* @return true if the whole data was read, false otherwise.
|
||||
*/
|
||||
gcc_nonnull_all
|
||||
void ReadFull(void *ptr, size_t size);
|
||||
void ReadFull(std::unique_lock<Mutex> &lock, void *ptr, size_t size);
|
||||
|
||||
/**
|
||||
* Wrapper for ReadFull() which locks and unlocks the mutex;
|
||||
|
@ -89,12 +89,13 @@ ProxyInputStream::Update() noexcept
|
||||
}
|
||||
|
||||
void
|
||||
ProxyInputStream::Seek(offset_type new_offset)
|
||||
ProxyInputStream::Seek(std::unique_lock<Mutex> &lock,
|
||||
offset_type new_offset)
|
||||
{
|
||||
while (!input)
|
||||
set_input_cond.wait(mutex);
|
||||
set_input_cond.wait(lock);
|
||||
|
||||
input->Seek(new_offset);
|
||||
input->Seek(lock, new_offset);
|
||||
CopyAttributes();
|
||||
}
|
||||
|
||||
@ -120,12 +121,13 @@ ProxyInputStream::IsAvailable() noexcept
|
||||
}
|
||||
|
||||
size_t
|
||||
ProxyInputStream::Read(void *ptr, size_t read_size)
|
||||
ProxyInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t read_size)
|
||||
{
|
||||
while (!input)
|
||||
set_input_cond.wait(mutex);
|
||||
set_input_cond.wait(lock);
|
||||
|
||||
size_t nbytes = input->Read(ptr, read_size);
|
||||
size_t nbytes = input->Read(lock, ptr, read_size);
|
||||
CopyAttributes();
|
||||
return nbytes;
|
||||
}
|
||||
|
@ -60,11 +60,13 @@ public:
|
||||
/* virtual methods from InputStream */
|
||||
void Check() override;
|
||||
void Update() noexcept override;
|
||||
void Seek(offset_type new_offset) override;
|
||||
void Seek(std::unique_lock<Mutex> &lock,
|
||||
offset_type new_offset) override;
|
||||
bool IsEOF() noexcept override;
|
||||
std::unique_ptr<Tag> ReadTag() noexcept override;
|
||||
bool IsAvailable() noexcept override;
|
||||
size_t Read(void *ptr, size_t read_size) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t read_size) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -60,8 +60,9 @@ public:
|
||||
return !ReadingFromBuffer() && ProxyInputStream::IsEOF();
|
||||
}
|
||||
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
void Seek(offset_type offset) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
void Seek(std::unique_lock<Mutex> &lock, offset_type offset) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
@ -74,7 +75,8 @@ private:
|
||||
};
|
||||
|
||||
size_t
|
||||
RewindInputStream::Read(void *ptr, size_t read_size)
|
||||
RewindInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t read_size)
|
||||
{
|
||||
if (ReadingFromBuffer()) {
|
||||
/* buffered read */
|
||||
@ -93,7 +95,7 @@ RewindInputStream::Read(void *ptr, size_t read_size)
|
||||
} else {
|
||||
/* pass method call to underlying stream */
|
||||
|
||||
size_t nbytes = input->Read(ptr, read_size);
|
||||
size_t nbytes = input->Read(lock, ptr, read_size);
|
||||
|
||||
if (input->GetOffset() > (offset_type)sizeof(buffer))
|
||||
/* disable buffering */
|
||||
@ -114,7 +116,7 @@ RewindInputStream::Read(void *ptr, size_t read_size)
|
||||
}
|
||||
|
||||
void
|
||||
RewindInputStream::Seek(offset_type new_offset)
|
||||
RewindInputStream::Seek(std::unique_lock<Mutex> &lock, offset_type new_offset)
|
||||
{
|
||||
assert(IsReady());
|
||||
|
||||
@ -132,7 +134,7 @@ RewindInputStream::Seek(offset_type new_offset)
|
||||
buffered range now */
|
||||
tail = 0;
|
||||
|
||||
ProxyInputStream::Seek(new_offset);
|
||||
ProxyInputStream::Seek(lock, new_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,8 @@ ThreadInputStream::IsAvailable() noexcept
|
||||
}
|
||||
|
||||
inline size_t
|
||||
ThreadInputStream::Read(void *ptr, size_t read_size)
|
||||
ThreadInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t read_size)
|
||||
{
|
||||
assert(!thread.IsInside());
|
||||
|
||||
@ -154,7 +155,7 @@ ThreadInputStream::Read(void *ptr, size_t read_size)
|
||||
return 0;
|
||||
|
||||
const ScopeExchangeInputStreamHandler h(*this, &cond_handler);
|
||||
cond_handler.cond.wait(mutex);
|
||||
cond_handler.cond.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,8 @@ public:
|
||||
void Check() override final;
|
||||
bool IsEOF() noexcept final;
|
||||
bool IsAvailable() noexcept final;
|
||||
size_t Read(void *ptr, size_t size) override final;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override final;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -91,8 +91,9 @@ class CdioParanoiaInputStream final : public InputStream {
|
||||
|
||||
/* virtual methods from InputStream */
|
||||
bool IsEOF() noexcept override;
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
void Seek(offset_type offset) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
void Seek(std::unique_lock<Mutex> &lock, offset_type offset) override;
|
||||
};
|
||||
|
||||
static constexpr Domain cdio_domain("cdio");
|
||||
@ -255,7 +256,8 @@ input_cdio_open(const char *uri,
|
||||
}
|
||||
|
||||
void
|
||||
CdioParanoiaInputStream::Seek(offset_type new_offset)
|
||||
CdioParanoiaInputStream::Seek(std::unique_lock<Mutex> &,
|
||||
offset_type new_offset)
|
||||
{
|
||||
if (new_offset > size)
|
||||
throw FormatRuntimeError("Invalid offset to seek %ld (%ld)",
|
||||
@ -276,7 +278,8 @@ CdioParanoiaInputStream::Seek(offset_type new_offset)
|
||||
}
|
||||
|
||||
size_t
|
||||
CdioParanoiaInputStream::Read(void *ptr, size_t length)
|
||||
CdioParanoiaInputStream::Read(std::unique_lock<Mutex> &,
|
||||
void *ptr, size_t length)
|
||||
{
|
||||
size_t nbytes = 0;
|
||||
char *wptr = (char *) ptr;
|
||||
|
@ -49,8 +49,10 @@ public:
|
||||
|
||||
/* virtual methods from InputStream */
|
||||
bool IsEOF() noexcept override;
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
void Seek(offset_type offset) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
void Seek(std::unique_lock<Mutex> &lock,
|
||||
offset_type offset) override;
|
||||
};
|
||||
|
||||
gcc_const
|
||||
@ -79,7 +81,8 @@ input_ffmpeg_open(const char *uri,
|
||||
}
|
||||
|
||||
size_t
|
||||
FfmpegInputStream::Read(void *ptr, size_t read_size)
|
||||
FfmpegInputStream::Read(std::unique_lock<Mutex> &,
|
||||
void *ptr, size_t read_size)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
@ -99,7 +102,7 @@ FfmpegInputStream::IsEOF() noexcept
|
||||
}
|
||||
|
||||
void
|
||||
FfmpegInputStream::Seek(offset_type new_offset)
|
||||
FfmpegInputStream::Seek(std::unique_lock<Mutex> &, offset_type new_offset)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
|
@ -48,8 +48,10 @@ public:
|
||||
return GetOffset() >= GetSize();
|
||||
}
|
||||
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
void Seek(offset_type offset) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
void Seek(std::unique_lock<Mutex> &lock,
|
||||
offset_type offset) override;
|
||||
};
|
||||
|
||||
InputStreamPtr
|
||||
@ -74,7 +76,8 @@ OpenFileInputStream(Path path, Mutex &mutex)
|
||||
}
|
||||
|
||||
void
|
||||
FileInputStream::Seek(offset_type new_offset)
|
||||
FileInputStream::Seek(std::unique_lock<Mutex> &,
|
||||
offset_type new_offset)
|
||||
{
|
||||
{
|
||||
const ScopeUnlock unlock(mutex);
|
||||
@ -85,7 +88,8 @@ FileInputStream::Seek(offset_type new_offset)
|
||||
}
|
||||
|
||||
size_t
|
||||
FileInputStream::Read(void *ptr, size_t read_size)
|
||||
FileInputStream::Read(std::unique_lock<Mutex> &,
|
||||
void *ptr, size_t read_size)
|
||||
{
|
||||
size_t nbytes;
|
||||
|
||||
|
@ -56,8 +56,9 @@ public:
|
||||
return offset >= size;
|
||||
}
|
||||
|
||||
size_t Read(void *ptr, size_t size) override;
|
||||
void Seek(offset_type offset) override;
|
||||
size_t Read(std::unique_lock<Mutex> &lock,
|
||||
void *ptr, size_t size) override;
|
||||
void Seek(std::unique_lock<Mutex> &lock, offset_type offset) override;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -118,7 +119,8 @@ input_smbclient_open(const char *uri,
|
||||
}
|
||||
|
||||
size_t
|
||||
SmbclientInputStream::Read(void *ptr, size_t read_size)
|
||||
SmbclientInputStream::Read(std::unique_lock<Mutex> &,
|
||||
void *ptr, size_t read_size)
|
||||
{
|
||||
ssize_t nbytes;
|
||||
|
||||
@ -136,7 +138,8 @@ SmbclientInputStream::Read(void *ptr, size_t read_size)
|
||||
}
|
||||
|
||||
void
|
||||
SmbclientInputStream::Seek(offset_type new_offset)
|
||||
SmbclientInputStream::Seek(std::unique_lock<Mutex> &,
|
||||
offset_type new_offset)
|
||||
{
|
||||
off_t result;
|
||||
|
||||
|
@ -39,14 +39,14 @@ struct aiff_chunk_header {
|
||||
};
|
||||
|
||||
size_t
|
||||
aiff_seek_id3(InputStream &is)
|
||||
aiff_seek_id3(InputStream &is, std::unique_lock<Mutex> &lock)
|
||||
{
|
||||
/* seek to the beginning and read the AIFF header */
|
||||
|
||||
is.Rewind();
|
||||
is.Rewind(lock);
|
||||
|
||||
aiff_header header;
|
||||
is.ReadFull(&header, sizeof(header));
|
||||
is.ReadFull(lock, &header, sizeof(header));
|
||||
if (memcmp(header.id, "FORM", 4) != 0 ||
|
||||
(is.KnownSize() && FromBE32(header.size) > is.GetSize()) ||
|
||||
(memcmp(header.format, "AIFF", 4) != 0 &&
|
||||
@ -57,7 +57,7 @@ aiff_seek_id3(InputStream &is)
|
||||
/* read the chunk header */
|
||||
|
||||
aiff_chunk_header chunk;
|
||||
is.ReadFull(&chunk, sizeof(chunk));
|
||||
is.ReadFull(lock, &chunk, sizeof(chunk));
|
||||
|
||||
size_t size = FromBE32(chunk.size);
|
||||
if (size > size_t(std::numeric_limits<int>::max()))
|
||||
@ -73,6 +73,6 @@ aiff_seek_id3(InputStream &is)
|
||||
/* pad byte */
|
||||
++size;
|
||||
|
||||
is.Skip(size);
|
||||
is.Skip(lock, size);
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,12 @@
|
||||
#ifndef MPD_AIFF_HXX
|
||||
#define MPD_AIFF_HXX
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
class InputStream;
|
||||
class Mutex;
|
||||
|
||||
/**
|
||||
* Seeks the AIFF file to the ID3 chunk.
|
||||
@ -38,6 +41,6 @@ class InputStream;
|
||||
* @return the size of the ID3 chunk
|
||||
*/
|
||||
size_t
|
||||
aiff_seek_id3(InputStream &is);
|
||||
aiff_seek_id3(InputStream &is, std::unique_lock<Mutex> &lock);
|
||||
|
||||
#endif
|
||||
|
@ -40,15 +40,15 @@ struct ApeFooter {
|
||||
bool
|
||||
tag_ape_scan(InputStream &is, ApeTagCallback callback)
|
||||
try {
|
||||
const std::lock_guard<Mutex> protect(is.mutex);
|
||||
std::unique_lock<Mutex> lock(is.mutex);
|
||||
|
||||
if (!is.KnownSize() || !is.CheapSeeking())
|
||||
return false;
|
||||
|
||||
/* determine if file has an apeV2 tag */
|
||||
ApeFooter footer;
|
||||
is.Seek(is.GetSize() - sizeof(footer));
|
||||
is.ReadFull(&footer, sizeof(footer));
|
||||
is.Seek(lock, is.GetSize() - sizeof(footer));
|
||||
is.ReadFull(lock, &footer, sizeof(footer));
|
||||
|
||||
if (memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0 ||
|
||||
FromLE32(footer.version) != 2000)
|
||||
@ -61,14 +61,14 @@ try {
|
||||
remaining > 1024 * 1024)
|
||||
return false;
|
||||
|
||||
is.Seek(is.GetSize() - remaining);
|
||||
is.Seek(lock, is.GetSize() - remaining);
|
||||
|
||||
/* read tag into buffer */
|
||||
remaining -= sizeof(footer);
|
||||
assert(remaining > 10);
|
||||
|
||||
std::unique_ptr<char[]> buffer(new char[remaining]);
|
||||
is.ReadFull(buffer.get(), remaining);
|
||||
is.ReadFull(lock, buffer.get(), remaining);
|
||||
|
||||
/* read tags */
|
||||
unsigned n = FromLE32(footer.count);
|
||||
|
@ -37,11 +37,12 @@ tag_is_id3v1(struct id3_tag *tag) noexcept
|
||||
}
|
||||
|
||||
static long
|
||||
get_id3v2_footer_size(InputStream &is, offset_type offset)
|
||||
get_id3v2_footer_size(InputStream &is, std::unique_lock<Mutex> &lock,
|
||||
offset_type offset)
|
||||
try {
|
||||
id3_byte_t buf[ID3_TAG_QUERYSIZE];
|
||||
is.Seek(offset);
|
||||
is.ReadFull(buf, sizeof(buf));
|
||||
is.Seek(lock, offset);
|
||||
is.ReadFull(lock, buf, sizeof(buf));
|
||||
|
||||
return id3_tag_query(buf, sizeof(buf));
|
||||
} catch (...) {
|
||||
@ -49,10 +50,10 @@ try {
|
||||
}
|
||||
|
||||
static UniqueId3Tag
|
||||
ReadId3Tag(InputStream &is)
|
||||
ReadId3Tag(InputStream &is, std::unique_lock<Mutex> &lock)
|
||||
try {
|
||||
id3_byte_t query_buffer[ID3_TAG_QUERYSIZE];
|
||||
is.ReadFull(query_buffer, sizeof(query_buffer));
|
||||
is.ReadFull(lock, query_buffer, sizeof(query_buffer));
|
||||
|
||||
/* Look for a tag header */
|
||||
long tag_size = id3_tag_query(query_buffer, sizeof(query_buffer));
|
||||
@ -72,7 +73,7 @@ try {
|
||||
|
||||
/* now read the remaining bytes */
|
||||
const size_t remaining = tag_size - sizeof(query_buffer);
|
||||
is.ReadFull(end, remaining);
|
||||
is.ReadFull(lock, end, remaining);
|
||||
|
||||
return UniqueId3Tag(id3_tag_parse(tag_buffer.get(), tag_size));
|
||||
} catch (...) {
|
||||
@ -80,20 +81,20 @@ try {
|
||||
}
|
||||
|
||||
static UniqueId3Tag
|
||||
ReadId3Tag(InputStream &is, offset_type offset)
|
||||
ReadId3Tag(InputStream &is, std::unique_lock<Mutex> &lock, offset_type offset)
|
||||
try {
|
||||
is.Seek(offset);
|
||||
is.Seek(lock, offset);
|
||||
|
||||
return ReadId3Tag(is);
|
||||
return ReadId3Tag(is, lock);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static UniqueId3Tag
|
||||
ReadId3v1Tag(InputStream &is)
|
||||
ReadId3v1Tag(InputStream &is, std::unique_lock<Mutex> &lock)
|
||||
try {
|
||||
id3_byte_t buffer[ID3V1_SIZE];
|
||||
is.ReadFull(buffer, ID3V1_SIZE);
|
||||
is.ReadFull(lock, buffer, ID3V1_SIZE);
|
||||
|
||||
return UniqueId3Tag(id3_tag_parse(buffer, ID3V1_SIZE));
|
||||
} catch (...) {
|
||||
@ -101,18 +102,19 @@ try {
|
||||
}
|
||||
|
||||
static UniqueId3Tag
|
||||
ReadId3v1Tag(InputStream &is, offset_type offset)
|
||||
ReadId3v1Tag(InputStream &is, std::unique_lock<Mutex> &lock,
|
||||
offset_type offset)
|
||||
try {
|
||||
is.Seek(offset);
|
||||
return ReadId3v1Tag(is);
|
||||
is.Seek(lock, offset);
|
||||
return ReadId3v1Tag(is, lock);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static UniqueId3Tag
|
||||
tag_id3_find_from_beginning(InputStream &is)
|
||||
tag_id3_find_from_beginning(InputStream &is, std::unique_lock<Mutex> &lock)
|
||||
try {
|
||||
auto tag = ReadId3Tag(is);
|
||||
auto tag = ReadId3Tag(is, lock);
|
||||
if (!tag) {
|
||||
return nullptr;
|
||||
} else if (tag_is_id3v1(tag.get())) {
|
||||
@ -129,7 +131,7 @@ try {
|
||||
break;
|
||||
|
||||
/* Get the tag specified by the SEEK frame */
|
||||
auto seektag = ReadId3Tag(is, is.GetOffset() + seek);
|
||||
auto seektag = ReadId3Tag(is, lock, is.GetOffset() + seek);
|
||||
if (!seektag || tag_is_id3v1(seektag.get()))
|
||||
break;
|
||||
|
||||
@ -143,7 +145,7 @@ try {
|
||||
}
|
||||
|
||||
static UniqueId3Tag
|
||||
tag_id3_find_from_end(InputStream &is)
|
||||
tag_id3_find_from_end(InputStream &is, std::unique_lock<Mutex> &lock)
|
||||
try {
|
||||
if (!is.KnownSize() || !is.CheapSeeking())
|
||||
return nullptr;
|
||||
@ -155,7 +157,7 @@ try {
|
||||
offset_type offset = size - ID3V1_SIZE;
|
||||
|
||||
/* Get an id3v1 tag from the end of file for later use */
|
||||
auto v1tag = ReadId3v1Tag(is, offset);
|
||||
auto v1tag = ReadId3v1Tag(is, lock, offset);
|
||||
if (!v1tag)
|
||||
offset = size;
|
||||
|
||||
@ -164,7 +166,7 @@ try {
|
||||
return v1tag;
|
||||
|
||||
long tag_offset =
|
||||
get_id3v2_footer_size(is, offset - ID3_TAG_QUERYSIZE);
|
||||
get_id3v2_footer_size(is, lock, offset - ID3_TAG_QUERYSIZE);
|
||||
if (tag_offset >= 0)
|
||||
return v1tag;
|
||||
|
||||
@ -173,7 +175,7 @@ try {
|
||||
return v1tag;
|
||||
|
||||
/* Get the tag which the footer belongs to */
|
||||
auto tag = ReadId3Tag(is, offset - tag_size);
|
||||
auto tag = ReadId3Tag(is, lock, offset - tag_size);
|
||||
if (!tag)
|
||||
return v1tag;
|
||||
|
||||
@ -184,13 +186,13 @@ try {
|
||||
}
|
||||
|
||||
static UniqueId3Tag
|
||||
tag_id3_riff_aiff_load(InputStream &is)
|
||||
tag_id3_riff_aiff_load(InputStream &is, std::unique_lock<Mutex> &lock)
|
||||
try {
|
||||
size_t size;
|
||||
try {
|
||||
size = riff_seek_id3(is);
|
||||
size = riff_seek_id3(is, lock);
|
||||
} catch (...) {
|
||||
size = aiff_seek_id3(is);
|
||||
size = aiff_seek_id3(is, lock);
|
||||
}
|
||||
|
||||
if (size > 4 * 1024 * 1024)
|
||||
@ -198,7 +200,7 @@ try {
|
||||
return nullptr;
|
||||
|
||||
std::unique_ptr<id3_byte_t[]> buffer(new id3_byte_t[size]);
|
||||
is.ReadFull(buffer.get(), size);
|
||||
is.ReadFull(lock, buffer.get(), size);
|
||||
|
||||
return UniqueId3Tag(id3_tag_parse(buffer.get(), size));
|
||||
} catch (...) {
|
||||
@ -208,13 +210,13 @@ try {
|
||||
UniqueId3Tag
|
||||
tag_id3_load(InputStream &is)
|
||||
try {
|
||||
const std::lock_guard<Mutex> protect(is.mutex);
|
||||
std::unique_lock<Mutex> lock(is.mutex);
|
||||
|
||||
auto tag = tag_id3_find_from_beginning(is);
|
||||
auto tag = tag_id3_find_from_beginning(is, lock);
|
||||
if (tag == nullptr && is.CheapSeeking()) {
|
||||
tag = tag_id3_riff_aiff_load(is);
|
||||
tag = tag_id3_riff_aiff_load(is, lock);
|
||||
if (tag == nullptr)
|
||||
tag = tag_id3_find_from_end(is);
|
||||
tag = tag_id3_find_from_end(is, lock);
|
||||
}
|
||||
|
||||
return tag;
|
||||
|
@ -39,14 +39,14 @@ struct riff_chunk_header {
|
||||
};
|
||||
|
||||
size_t
|
||||
riff_seek_id3(InputStream &is)
|
||||
riff_seek_id3(InputStream &is, std::unique_lock<Mutex> &lock)
|
||||
{
|
||||
/* seek to the beginning and read the RIFF header */
|
||||
|
||||
is.Rewind();
|
||||
is.Rewind(lock);
|
||||
|
||||
riff_header header;
|
||||
is.ReadFull(&header, sizeof(header));
|
||||
is.ReadFull(lock, &header, sizeof(header));
|
||||
if (memcmp(header.id, "RIFF", 4) != 0 ||
|
||||
(is.KnownSize() && FromLE32(header.size) > is.GetSize()))
|
||||
throw std::runtime_error("Not a RIFF file");
|
||||
@ -55,7 +55,7 @@ riff_seek_id3(InputStream &is)
|
||||
/* read the chunk header */
|
||||
|
||||
riff_chunk_header chunk;
|
||||
is.ReadFull(&chunk, sizeof(chunk));
|
||||
is.ReadFull(lock, &chunk, sizeof(chunk));
|
||||
|
||||
size_t size = FromLE32(chunk.size);
|
||||
if (size > size_t(std::numeric_limits<int>::max()))
|
||||
@ -72,6 +72,6 @@ riff_seek_id3(InputStream &is)
|
||||
/* pad byte */
|
||||
++size;
|
||||
|
||||
is.Skip(size);
|
||||
is.Skip(lock, size);
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,11 @@
|
||||
#ifndef MPD_RIFF_HXX
|
||||
#define MPD_RIFF_HXX
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
class Mutex;
|
||||
class InputStream;
|
||||
|
||||
/**
|
||||
@ -38,6 +41,6 @@ class InputStream;
|
||||
* @return the size of the ID3 chunk
|
||||
*/
|
||||
size_t
|
||||
riff_seek_id3(InputStream &is);
|
||||
riff_seek_id3(InputStream &is, std::unique_lock<Mutex> &lock);
|
||||
|
||||
#endif
|
||||
|
@ -28,7 +28,8 @@ public:
|
||||
return remaining == 0;
|
||||
}
|
||||
|
||||
size_t Read(void *ptr, size_t read_size) override {
|
||||
size_t Read(std::unique_lock<Mutex> &,
|
||||
void *ptr, size_t read_size) override {
|
||||
size_t nbytes = std::min(remaining, read_size);
|
||||
memcpy(ptr, data, nbytes);
|
||||
data += nbytes;
|
||||
@ -51,7 +52,7 @@ TEST(RewindInputStream, Basic)
|
||||
EXPECT_TRUE(ris.get() != sis);
|
||||
EXPECT_TRUE(ris != nullptr);
|
||||
|
||||
const std::lock_guard<Mutex> protect(mutex);
|
||||
std::unique_lock<Mutex> lock(mutex);
|
||||
|
||||
ris->Update();
|
||||
EXPECT_TRUE(ris->IsReady());
|
||||
@ -59,50 +60,50 @@ TEST(RewindInputStream, Basic)
|
||||
EXPECT_EQ(offset_type(0), ris->GetOffset());
|
||||
|
||||
char buffer[16];
|
||||
size_t nbytes = ris->Read(buffer, 2);
|
||||
size_t nbytes = ris->Read(lock, buffer, 2);
|
||||
EXPECT_EQ(size_t(2), nbytes);
|
||||
EXPECT_EQ('f', buffer[0]);
|
||||
EXPECT_EQ('o', buffer[1]);
|
||||
EXPECT_EQ(offset_type(2), ris->GetOffset());
|
||||
EXPECT_FALSE(ris->IsEOF());
|
||||
|
||||
nbytes = ris->Read(buffer, 2);
|
||||
nbytes = ris->Read(lock, buffer, 2);
|
||||
EXPECT_EQ(size_t(2), nbytes);
|
||||
EXPECT_EQ('o', buffer[0]);
|
||||
EXPECT_EQ(' ', buffer[1]);
|
||||
EXPECT_EQ(offset_type(4), ris->GetOffset());
|
||||
EXPECT_FALSE(ris->IsEOF());
|
||||
|
||||
ris->Seek(1);
|
||||
ris->Seek(lock, 1);
|
||||
EXPECT_EQ(offset_type(1), ris->GetOffset());
|
||||
EXPECT_FALSE(ris->IsEOF());
|
||||
|
||||
nbytes = ris->Read(buffer, 2);
|
||||
nbytes = ris->Read(lock, buffer, 2);
|
||||
EXPECT_EQ(size_t(2), nbytes);
|
||||
EXPECT_EQ('o', buffer[0]);
|
||||
EXPECT_EQ('o', buffer[1]);
|
||||
EXPECT_EQ(offset_type(3), ris->GetOffset());
|
||||
EXPECT_FALSE(ris->IsEOF());
|
||||
|
||||
ris->Seek(0);
|
||||
ris->Seek(lock, 0);
|
||||
EXPECT_EQ(offset_type(0), ris->GetOffset());
|
||||
EXPECT_FALSE(ris->IsEOF());
|
||||
|
||||
nbytes = ris->Read(buffer, 2);
|
||||
nbytes = ris->Read(lock, buffer, 2);
|
||||
EXPECT_EQ(size_t(2), nbytes);
|
||||
EXPECT_EQ('f', buffer[0]);
|
||||
EXPECT_EQ('o', buffer[1]);
|
||||
EXPECT_EQ(offset_type(2), ris->GetOffset());
|
||||
EXPECT_FALSE(ris->IsEOF());
|
||||
|
||||
nbytes = ris->Read(buffer, sizeof(buffer));
|
||||
nbytes = ris->Read(lock, buffer, sizeof(buffer));
|
||||
EXPECT_EQ(size_t(2), nbytes);
|
||||
EXPECT_EQ('o', buffer[0]);
|
||||
EXPECT_EQ(' ', buffer[1]);
|
||||
EXPECT_EQ(offset_type(4), ris->GetOffset());
|
||||
EXPECT_FALSE(ris->IsEOF());
|
||||
|
||||
nbytes = ris->Read(buffer, sizeof(buffer));
|
||||
nbytes = ris->Read(lock, buffer, sizeof(buffer));
|
||||
EXPECT_EQ(size_t(3), nbytes);
|
||||
EXPECT_EQ('b', buffer[0]);
|
||||
EXPECT_EQ('a', buffer[1]);
|
||||
@ -110,11 +111,11 @@ TEST(RewindInputStream, Basic)
|
||||
EXPECT_EQ(offset_type(7), ris->GetOffset());
|
||||
EXPECT_TRUE(ris->IsEOF());
|
||||
|
||||
ris->Seek(3);
|
||||
ris->Seek(lock, 3);
|
||||
EXPECT_EQ(offset_type(3), ris->GetOffset());
|
||||
EXPECT_FALSE(ris->IsEOF());
|
||||
|
||||
nbytes = ris->Read(buffer, sizeof(buffer));
|
||||
nbytes = ris->Read(lock, buffer, sizeof(buffer));
|
||||
EXPECT_EQ(size_t(4), nbytes);
|
||||
EXPECT_EQ(' ', buffer[0]);
|
||||
EXPECT_EQ('b', buffer[1]);
|
||||
|
@ -131,7 +131,7 @@ tag_save(FILE *file, const Tag &tag)
|
||||
static int
|
||||
dump_input_stream(InputStream *is)
|
||||
{
|
||||
const std::lock_guard<Mutex> protect(is->mutex);
|
||||
std::unique_lock<Mutex> lock(is->mutex);
|
||||
|
||||
/* print meta data */
|
||||
|
||||
@ -150,7 +150,7 @@ dump_input_stream(InputStream *is)
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
size_t num_read = is->Read(buffer, sizeof(buffer));
|
||||
size_t num_read = is->Read(lock, buffer, sizeof(buffer));
|
||||
if (num_read == 0)
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user