* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* ubs-io is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef BOOSTIO_SLICE_H
#define BOOSTIO_SLICE_H
#include <functional>
#include <sstream>
#include <vector>
#include "bio_err.h"
#include "bio_lock.h"
#include "bio_log.h"
#include "bio_ref.h"
#include "flow_type.h"
#include "net_common.h"
#include "securec.h"
namespace ock {
namespace bio {
class Slice;
using SlicePtr = Ref<Slice>;
class SliceSerializer {
public:
virtual ~SliceSerializer() = default;
virtual std::string ToString() = 0;
virtual uint64_t GetSerializeLen() = 0;
virtual BResult Serialize(char *data, uint64_t dataLen, uint64_t &length) = 0;
virtual BResult Deserialize(char *data, uint64_t length) = 0;
};
class Slice : public SliceSerializer {
public:
Slice() = default;
Slice(uint64_t length, std::vector<FlowAddr> &addrs, FlowType flowType = FLOW_MEMORY)
: mFlowType(flowType),
mLength(length),
mAddrs(std::move(addrs))
{
}
~Slice() override = default;
inline FlowType GetFlowType() const
{
return mFlowType;
}
inline uint64_t GetLength() const
{
return mLength;
}
inline const std::vector<FlowAddr> &GetAddrs() const
{
return mAddrs;
}
bool IsTheSameWith(const SlicePtr &other);
SlicePtr Split(uint64_t offset, uint64_t length);
std::string ToString() override;
uint64_t GetSerializeLen() override;
BResult Serialize(char *data, uint64_t dataLen, uint64_t &length) override;
BResult Deserialize(char *data, uint64_t length) override;
inline uint32_t GetDataCrc() const
{
return mdataCrc;
}
inline void SetDataCrc(uint32_t crc)
{
mdataCrc = crc;
}
BResult CalculateDataCrc(uint32_t &valueCrc, uint64_t dataOffset, uint64_t dataLength);
BResult VerifyDataCrc(uint32_t originCrc, uint64_t dataOffset, uint64_t dataLength, Slice *slice);
DEFINE_REF_COUNT_FUNCTIONS;
protected:
DEFINE_REF_COUNT_VARIABLE;
private:
uint32_t mdataCrc{0};
FlowType mFlowType{FLOW_MEMORY};
uint64_t mLength{0};
std::vector<FlowAddr> mAddrs;
};
enum SliceState : uint8_t
{
SLICE_VALID = 1,
SLICE_INVALID = 2,
};
template <typename S>
class SliceRef {
public:
explicit SliceRef(const S &slice) : mSlice(slice), mRef(0) {}
inline bool Aquire()
{
bool isSucceed = false;
std::lock_guard<std::mutex> lock(mSliceLock);
if (mSlice != nullptr && mState == SLICE_VALID) {
++mRef;
isSucceed = true;
}
return isSucceed;
}
inline void Release()
{
S execSlice = nullptr;
SetSliceCallback execSliceCallback = nullptr;
{
std::lock_guard<std::mutex> lock(mSliceLock);
--mRef;
if (mRef == 0 && mSetSliceCallback != nullptr) {
execSlice = mSlice;
mSlice = mNewSlice;
execSliceCallback = mSetSliceCallback;
mNewSlice = nullptr;
mSetSliceCallback = nullptr;
}
}
if (execSliceCallback != nullptr) {
execSliceCallback(execSlice);
}
}
inline bool OpLock()
{
bool expectval = false;
if (mOpLock.compare_exchange_weak(expectval, true)) {
return true;
}
return false;
}
inline void OpUnLock()
{
mOpLock = false;
}
inline void SetState(SliceState state)
{
mState = state;
}
inline SliceState GetState() const
{
return mState;
}
inline bool Test()
{
return mRef > 0;
}
inline S &GetSlice()
{
return mSlice;
}
using SetSliceCallback = std::function<void(const S &oldSlice)>;
void SetSlice(const S &newSlice, SetSliceCallback &setSliceCallback)
{
S execSlice = nullptr;
SetSliceCallback execSliceCallback = nullptr;
{
std::lock_guard<std::mutex> lock(mSliceLock);
if (mRef == 0) {
execSlice = mSlice;
mSlice = newSlice;
execSliceCallback = setSliceCallback;
} else {
mNewSlice = newSlice;
mSetSliceCallback = setSliceCallback;
}
}
if (execSliceCallback != nullptr) {
execSliceCallback(execSlice);
}
}
DEFINE_REF_COUNT_FUNCTIONS;
private:
std::mutex mSliceLock;
S mSlice{nullptr};
S mNewSlice{nullptr};
SetSliceCallback mSetSliceCallback{nullptr};
std::atomic<uint64_t> mRef{0};
std::atomic<bool> mOpLock{false};
std::atomic<SliceState> mState{SLICE_VALID};
DEFINE_REF_COUNT_VARIABLE;
};
using SliceRefPtr = Ref<SliceRef<SlicePtr>>;
}
}
#endif