#include <google/protobuf/io/zero_copy_stream.h>
namespace google::protobuf::io
Esse arquivo contém as interfaces ZeroCopyInputStream e ZeroCopyOutputStream, que representam streams de E/S abstratos de e para os quais os buffers de protocolo podem ser lidos e gravados.
Para ver implementações simples dessas interfaces, consulte zero_copy_stream_impl.h.
Essas interfaces são diferentes dos fluxos clássicos de E/S porque tentam minimizar a quantidade de cópias de dados que precisam ser feitas. Para fazer isso, a responsabilidade de alocar buffers é movida para o objeto de stream, em vez de ser a responsabilidade do autor da chamada. Assim, o stream pode retornar um buffer que realmente aponta diretamente para a estrutura de dados final, onde os bytes serão armazenados, e o autor da chamada pode interagir diretamente com esse buffer, eliminando uma operação de cópia intermediária.
Por exemplo, considere o caso comum em que você está lendo bytes de uma matriz que já está na memória (ou talvez em um arquivo mmap()ed). Com as transmissões clássicas de E/S, você faria algo como:
char buffer[[]BUFFER_SIZE]; input->Read(buffer, BUFFER_SIZE); DoSomething(buffer, BUFFER_SIZE);
O stream basicamente chama memcpy() para copiar os dados da matriz para o buffer. Com um ZeroCopyInputStream, você faria isso:
const void* buffer; int size; input->Next(&buffer, &size); DoSomething(buffer, size);
Aqui, nenhuma cópia é realizada. O stream de entrada retorna um ponteiro diretamente para a matriz de apoio, e o autor da chamada acaba lendo diretamente dela.
Se você quiser ler de uma forma antiga, crie um CodedInputStream ou CodedOutputStream encapsulando esses objetos e usando os métodos ReadRaw()/WriteRaw(). Obviamente, elas vão adicionar uma etapa de cópia, mas o Coded*Stream processará o buffer para que pelo menos seja razoavelmente eficiente.
Exemplo de ZeroCopyInputStream:
// Read in a file and print its contents to stdout. int fd = open("myfile", O_RDONLY); ZeroCopyInputStream* input = new FileInputStream(fd); const void* buffer; int size; while (input->Next(&buffer, &size)) { cout.write(buffer, size); } delete input; close(fd);
Exemplo de ZeroCopyOutputStream:
// Copy the contents of "infile" to "outfile", using plain read() for // "infile" but a ZeroCopyOutputStream for "outfile". int infd = open("infile", O_RDONLY); int outfd = open("outfile", O_WRONLY); ZeroCopyOutputStream* output = new FileOutputStream(outfd); void* buffer; int size; while (output->Next(&buffer, &size)) { int bytes = read(infd, buffer, size); if (bytes < size) { // Reached EOF. output->BackUp(size - bytes); break; } } delete output; close(infd); close(outfd);
Turmas neste arquivo | |
---|---|
Interface abstrata semelhante a um fluxo de entrada, mas projetada para minimizar a cópia. | |
Interface abstrata semelhante a um stream de saída, mas projetada para minimizar a cópia. |
classe ZeroCopyInputStream
#include <google/protobuf/io/zero_copy_stream.h>
namespace google::protobuf::io
Interface abstrata semelhante a um fluxo de entrada, mas projetada para minimizar a cópia.
Subclasses conhecidas:
ArrayInputStream
ConcatenatingInputStream
CopyingInputStreamAdaptor
FileInputStream
IstreamInputStream
LimitingInputStream
Participantes | |
---|---|
| ZeroCopyInputStream() |
virtual | ~ZeroCopyInputStream() |
virtual bool | Next(const void ** data, int * size) = 0 Recebe um bloco de dados do stream. mais… |
virtual void | BackUp(int count) = 0 |
virtual bool | Skip(int count) = 0 Ignora vários bytes. mais… |
virtual int64_t | ByteCount() const = 0 Retorna o número total de bytes lidos desde que o objeto foi criado. |
virtual bool ZeroCopyInputStream::Next(
const void ** data,
int * size) = 0
const void ** data,
int * size) = 0
Recebe um bloco de dados do stream.
Condições prévias:
- "size" e "data" não são NULL.
Pós-condições:
- Se o valor retornado for falso, não haverá mais dados para retornar ou ocorreu um erro. Todos os erros são permanentes.
- Caso contrário, "size" aponta para o número real de bytes lidos e "data" aponta para um ponteiro para um buffer que contém esses bytes.
- A propriedade desse buffer permanece com o stream e ele permanece válido somente até que algum outro método do stream seja chamado ou que o stream seja destruído.
- É permitido que o buffer retornado tenha tamanho zero, desde que chamar Next() várias vezes produz um buffer com tamanho diferente de zero.
virtual void ZeroCopyInputStream::BackUp(
int count) = 0
int count) = 0
Faz backup de vários bytes, de modo que a próxima chamada para Next() retorna dados que já foram retornados pela última chamada para Next().
Isso é útil ao escrever procedimentos que apenas devem ler um certo ponto da entrada e retornar. Se Next() retornar um buffer que vai além do que você quer ler, use BackUp() para voltar ao ponto em que quer concluir.
Condições prévias:
- O último método chamado precisa ter sido Next().
- a contagem deve ser menor ou igual ao tamanho do último buffer retornado por Next().
Pós-condições:
virtual bool ZeroCopyInputStream::Skip(
int count) = 0
int count) = 0
Ignora vários bytes.
Retorna falso se o final do stream for alcançado ou se ocorrer algum erro de entrada. No caso de fim do stream, ele é avançado para o final (de modo que ByteCount() retorna o tamanho total do stream).
classe ZeroCopyOutputStream
#include <google/protobuf/io/zero_copy_stream.h>
namespace google::protobuf::io
Interface abstrata semelhante a um stream de saída, mas projetada para minimizar a cópia.
Subclasses conhecidas:
Participantes | |
---|---|
| ZeroCopyOutputStream() |
virtual | ~ZeroCopyOutputStream() |
virtual bool | Next(void ** data, int * size) = 0 Recebe um buffer em que os dados podem ser gravados. mais… |
virtual void | BackUp(int count) = 0 |
virtual int64_t | ByteCount() const = 0 Retorna o número total de bytes gravados desde que o objeto foi criado. |
virtual bool | WriteAliasedRaw(const void * data, int size) Gravar um determinado bloco de dados na saída. mais… |
virtual bool | AllowsAliasing() const |
virtual bool ZeroCopyOutputStream::Next(
void ** data,
int * size) = 0
void ** data,
int * size) = 0
Recebe um buffer em que os dados podem ser gravados.
Todos os dados gravados nesse buffer serão gravados na saída (talvez instantaneamente, talvez mais tarde).
Condições prévias:
- "size" e "data" não são NULL.
Pós-condições:
- Se o valor retornado for “false”, significa que ocorreu um erro. Todos os erros são permanentes.
- Caso contrário, "tamanho" apontará para o número real de bytes no buffer e "dados" aponta para o buffer.
- A propriedade desse buffer permanece com o stream e ele permanece válido somente até que algum outro método do stream seja chamado ou que o stream seja destruído.
- Todos os dados armazenados pelo autor da chamada nesse buffer serão gravados na saída (a menos que BackUp() seja chamado).
- É permitido que o buffer retornado tenha tamanho zero, desde que chamar Next() várias vezes produz um buffer com tamanho diferente de zero.
virtual void ZeroCopyOutputStream::BackUp(
int count) = 0
int count) = 0
Faz backup de vários bytes, de modo que o fim do último buffer retornado por Next() não seja gravado.
Isso é necessário quando você termina de gravar todos os dados que quer gravar, mas o último buffer foi maior do que o necessário. Não é recomendável escrever vários lixo após o término dos dados, então use BackUp() para fazer backup.
Condições prévias:
- O último método chamado precisa ter sido Next().
- a contagem deve ser menor ou igual ao tamanho do último buffer retornado por Next().
- O autor da chamada não pode ter escrito nada para os últimos bytes de "contagem" desse buffer.
Pós-condições:
- Os últimos bytes de "count" do último buffer retornados por Next() serão ignorados.
virtual bool ZeroCopyOutputStream::WriteAliasedRaw(
const void * data,
int size)
const void * data,
int size)
Gravar um determinado bloco de dados na saída.
Alguns streams de saída podem implementar isso de modo a evitar a cópia. Verifique AllowAliasing() antes de chamar WriteAliasedRaw(). Ocorrerá uma falha na GOOGLE_CHECK se o WriteAliasedRaw() for chamado em um stream que não permita o alias.
OBSERVAÇÃO: é responsabilidade do autor da chamada garantir que o bloco de memória permaneça ativo até que todos os dados tenham sido consumidos pelo stream.