295 lines
5.3 KiB
C++
Executable File
295 lines
5.3 KiB
C++
Executable File
// TJP COPYRIGHT HEADER
|
|
|
|
#include "Pipe.h"
|
|
#include <tjp/core/assert/debug_assert.h>
|
|
|
|
namespace tjp {
|
|
namespace core {
|
|
|
|
template<typename Packet, typename Mutex>
|
|
Pipe<Packet,Mutex>::Pipe () :
|
|
offset(0),
|
|
size_(0),
|
|
open(true)
|
|
{
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
Pipe<Packet,Mutex>::~Pipe ()
|
|
{
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
void Pipe<Packet,Mutex>::close()
|
|
{
|
|
auto l = lock_of(mutex);
|
|
|
|
open = false;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
bool Pipe<Packet,Mutex>::isOpen() const
|
|
{
|
|
auto l = lock_of(mutex);
|
|
return open;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::write_no_lock (Packet &&packet)
|
|
{
|
|
debug_assert(mutex.locked_by_caller());
|
|
|
|
if (packet.size() == 0)
|
|
return size_;
|
|
|
|
size_ += packet.size();
|
|
pipe.emplace_back(std::move(packet));
|
|
|
|
return size_;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::write (Packet &&packet)
|
|
{
|
|
auto l = lock_of(mutex);
|
|
|
|
return write_no_lock(std::move(packet));
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
Packet Pipe<Packet,Mutex>::read_no_lock ()
|
|
{
|
|
debug_assert(!pipe.empty());
|
|
debug_assert(offset == 0);
|
|
debug_assert(mutex.locked_by_caller());
|
|
|
|
auto p = std::move(pipe.front());
|
|
pipe.pop_front();
|
|
|
|
debug_assert(size_ >= p.size());
|
|
size_ -= p.size();
|
|
offset = 0;
|
|
return p;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
Packet Pipe<Packet,Mutex>::read ()
|
|
{
|
|
auto l = lock_of(mutex);
|
|
|
|
return read_no_lock();
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
bool Pipe<Packet,Mutex>::empty_no_lock() const
|
|
{
|
|
return pipe.empty();
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
bool Pipe<Packet,Mutex>::empty() const
|
|
{
|
|
auto l = lock_of(mutex);
|
|
|
|
return empty_no_lock();
|
|
}
|
|
|
|
// ---------------------
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::peek_no_lock (char *buffer, size_t size) const
|
|
{
|
|
debug_assert(mutex.locked_by_caller());
|
|
|
|
size_t ptr = 0;
|
|
size_t offset = this->offset;
|
|
|
|
auto &buffers = pipe;
|
|
|
|
typename PacketList::const_iterator i=buffers.begin();
|
|
while (i!=buffers.end() && (size > 0))
|
|
{
|
|
auto chunksize = i->size() - offset;
|
|
size_t newoffset = 0;
|
|
|
|
if (chunksize > size)
|
|
{
|
|
newoffset = offset + size;
|
|
chunksize = size;
|
|
}
|
|
|
|
if (buffer)
|
|
memcpy (buffer + ptr, i->data() + offset, chunksize);
|
|
|
|
ptr += chunksize;
|
|
size -= chunksize;
|
|
offset = newoffset;
|
|
|
|
i++;
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::peek (char *buffer, size_t size) const
|
|
{
|
|
auto l = lock_of(mutex);
|
|
|
|
return peek_no_lock(buffer, size);
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::read_no_lock (char *buffer, size_t requestedSize)
|
|
{
|
|
auto size = requestedSize;
|
|
size_t ptr = 0;
|
|
|
|
auto &buffers = pipe;
|
|
|
|
while (!buffers.empty() && (size > 0))
|
|
{
|
|
auto chunksize = buffers.front().size() - offset;
|
|
size_t newoffset = 0;
|
|
|
|
if (chunksize > size)
|
|
{
|
|
newoffset = offset + size;
|
|
chunksize = size;
|
|
}
|
|
|
|
if (buffer)
|
|
{
|
|
debug_assert(ptr + chunksize <= requestedSize);
|
|
memcpy (buffer + ptr, buffers.front().data() + offset, chunksize);
|
|
}
|
|
|
|
ptr += chunksize;
|
|
size -= chunksize;
|
|
offset = newoffset;
|
|
|
|
if (offset == 0)
|
|
{
|
|
size_ -= buffers.front().size();
|
|
buffers.pop_front();
|
|
}
|
|
}
|
|
|
|
sizeReadRequested += requestedSize;
|
|
sizeRead += ptr;
|
|
|
|
return ptr;
|
|
} ;
|
|
|
|
template<typename Packet, typename Mutex>
|
|
void Pipe<Packet,Mutex>::clearSizeRead ()
|
|
{
|
|
sizeReadRequested = sizeRead = 0;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::read (char *buffer, size_t requestedSize)
|
|
{
|
|
auto l = lock_of(mutex);
|
|
return read_no_lock(buffer, requestedSize);
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::write (const char *buffer, size_t size)
|
|
{
|
|
if (size == 0)
|
|
return size;
|
|
|
|
write(Packet(buffer, buffer+size));
|
|
return size;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::skip_no_lock(size_t size)
|
|
{
|
|
return read_no_lock(nullptr, size);
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::skip(size_t size)
|
|
{
|
|
auto l = lock_of(mutex);
|
|
|
|
return skip_no_lock(size);
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::size () const
|
|
{
|
|
auto l = lock_of(mutex);
|
|
return size_ - offset;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
void Pipe<Packet,Mutex>::clear ()
|
|
{
|
|
auto l = lock_of(mutex);
|
|
|
|
pipe.clear();
|
|
size_ = offset = 0;
|
|
flush_ = false;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
size_t Pipe<Packet,Mutex>::resize (size_t maximumSize)
|
|
{
|
|
auto l = lock_of(mutex);
|
|
if (size_ > maximumSize)
|
|
{
|
|
skip_no_lock(size_ - maximumSize);
|
|
}
|
|
|
|
return size_;
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
const Packet *Pipe<Packet,Mutex>::peek() const
|
|
{
|
|
auto l = lock_of(mutex);
|
|
|
|
if (pipe.empty())
|
|
return nullptr;
|
|
|
|
return &pipe.front();
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
bool Pipe<Packet,Mutex>::eos() const
|
|
{
|
|
return !open && empty();
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
bool Pipe<Packet,Mutex>::finishing() const
|
|
{
|
|
return !open && !empty();
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
bool Pipe<Packet,Mutex>::flushing() const
|
|
{
|
|
return flush_ && !empty();
|
|
}
|
|
|
|
template<typename Packet, typename Mutex>
|
|
bool Pipe<Packet,Mutex>::flushed()
|
|
{
|
|
if (!flush_)
|
|
return false;
|
|
|
|
if (!empty())
|
|
return false;
|
|
|
|
flush_ = false;
|
|
return true;
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace
|
|
|