gRPC ProtoBufferWriter

ProtoBufferWriter

protobuf 类 ZeroCopyOutputStream的一个特化。
原理是一次给予proto层一个字节的buffer,它能够被用于序列化消息的下一部分,如果上一次被分配的buffer多余需要的,使用选项"backup"。

class ProtoBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream {
public:
	ProtoBufferWriter(ByteBuffer* byte_buffer, int block_size, int total_size)
		: block_size_(block_size),
		  total_size_(total_size),
		  byte_count_(0),
		  have_backup_(false) {
		GPR_CODEGEN_ASSERT(!byte_buffer->Valid());
		grpc_byte_buffer* bp =
			g_core_codegen_interface->grpc_raw_byte_buffer_create(NULL, 0);
		byte_buffer->set_buffer(bp);
		slice_buffer_ = &bp->data.raw.slice_buffer;
	}
	~ProtoBufferWrite() {
		if(have_backup_)) {
			g_core_codegen_interface->grpc_slice_unref(backup_slice_);
		}
	}
	
	bool Next(void** data, int*size) override {
		// 1. Use the remaining backup slice if we have one
		// 2. Otherwise allocate a slice, up to the remaining length needed
		//    or our maximum allocation size
		// 3. Provide the slice start and size available
		// 4. Add the slice being returned to the slice buffer
 		GRP_CODEGEN_ASSERT(byte_count_ < total_size_);
		size_t remain = static_cast<size_t>(total_size_ - byte_count_);
		if (have_backup_) {
			slice_ = backup_slice_;
			have_backup_ = false;
			if(GRPC_SLICE_LENGTH(slice_) > remain) {
				GRPC_SLICE_SET_LENGTH(slice_, remain);
			}
		} else {
			// When less than a whole block is needed, only allocate that much.
			// But make sure the allocated slice is not inlined.
			size_t allocate_length = 
				reamin > static_cast<size_t>(block_size_) ? block_size_ : remain;
			slice_ = g_core_codegen_interface->grpc_slice_malloc(
				allocate_length > GRPC_SLICE_INLINED_SIZE ?
				allocate_length : GRPC_SLICE_INLINE_SIZE + 1);
		}
		*data = GRPC_SLICE_START_PTR(slice_);
		GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
		byte_count_ += *size = (int)GRPC_SLICE_LENGTH(slice_);
		g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
		return true;
	}
	
	// Backup by \a count bytes because Next returned more bytes than nedded
	// (only use in the last buffer). \a count must be less than or equal too
	// the last buffer returned form next;
	  void BackUp(int count) override {
    /// 1. Remove the partially-used last slice from the slice buffer
    /// 2. Split it into the needed (if any) and unneeded part
    /// 3. Add the needed part back to the slice buffer
    /// 4. Mark that we still have the remaining part (for later use/unref)
    GPR_CODEGEN_ASSERT(count <= static_cast<int>(GRPC_SLICE_LENGTH(slice_)));
    g_core_codegen_interface->grpc_slice_buffer_pop(slice_buffer_);
    if ((size_t)count == GRPC_SLICE_LENGTH(slice_)) {
      backup_slice_ = slice_;
    } else {
      backup_slice_ = g_core_codegen_interface->grpc_slice_split_tail(
          &slice_, GRPC_SLICE_LENGTH(slice_) - count);
      g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
    }
    // It's dangerous to keep an inlined grpc_slice as the backup slice, since
    // on a following Next() call, a reference will be returned to this slice
    // via GRPC_SLICE_START_PTR, which will not be an address held by
    // slice_buffer_.
    have_backup_ = backup_slice_.refcount != NULL;
    byte_count_ -= count;
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值