C++享元结构文档样式应用

21 篇文章 0 订阅

class BaseStyle {
public:
    enum ProperyID{
        PROP_FONT_SIZE,
        PROP_PARAGRAPH_INDENT
    };
//    virtual bool createLocalStyle();
    virtual void setProperty(int type, void* val) = 0;
};
using BaseStyleSp = std::shared_ptr<BaseStyle>;

class ShareData {
public:
    ShareData(float fontSize): m_fontSize(fontSize){}
    size_t hash() const { return std::hash<float>()(m_fontSize);}
public:
    float m_fontSize;
};
using ShareDataSp = std::shared_ptr<ShareData>;
using ShareDataWp = std::weak_ptr<ShareData>;

class ShareDocData {
public:
    float paragraphIndent;
};
using ShareDocDataSp = std::shared_ptr<ShareDocData>;
using ShareDocDataWp = std::weak_ptr<ShareDocData>;

class ShareDataLRU {
public:
    ShareDataLRU(): m_hitCount(0) {}
    int m_hitCount;
};

#include <cassert>
#include <unordered_map>
class ShareDataMergeManger{
    class CharHash {
    public:
        std::size_t operator()(const ShareDataSp &sharedPtr) const {
            if(!sharedPtr)
                return 0;
            return sharedPtr->hash();
        }
    };
    class CharCmp {
    public:
        bool operator()(const ShareDataSp &selfPtr, const ShareDataSp &otherPtr) const {
            if(selfPtr == otherPtr)
                return true;
            if(!selfPtr)
                return false;
            if(!otherPtr)
                return false;
            return selfPtr->hash() == otherPtr->hash();
        }
    };

public:
    ShareDataSp allocCharData(const ShareDataSp charData) {
        //if(manger.size() > 20000)
         //   clearUnUsed();
        return std::make_shared<ShareData>(*charData);
    }
    ShareDataSp addCacheCharData(const ShareDataSp& data) {
        auto ret = manger.emplace(data, ShareDataLRU());
        if(ret.second) { //新添加成功
            return ret.first->first;
        } else { //已存在,返回旧的
            ++ret.first->second.m_hitCount;
            return ret.first->first;
        }
    }
    ShareDataSp findCharData(const ShareDataSp& data) {
        auto shareData = manger.find(data);
        if(shareData == manger.end()) {
            return nullptr;
        }
        else {
            ++shareData->second.m_hitCount; //查找次数+1,热度上升
            return shareData->first;
        }
    }
    void removeCharData(const ShareDataSp& data) {
        manger.erase(data);
    }
    // 内存超过指定长度,自动清除未使用的区域
    void clearUnUsed() {
        for (auto iter = manger.begin(); iter != manger.end(); ) {
            if(1 == iter->first.use_count())
                iter = manger.erase(iter);
            else
                ++iter;
        }
    }
public:
    std::unordered_map<ShareDataSp, ShareDataLRU, CharHash, CharCmp> manger;
};
using ShareDataMergeMangerSp = std::shared_ptr<ShareDataMergeManger>;
using ShareDataMergeMangerWp = std::weak_ptr<ShareDataMergeManger>;

class LocalStyle : public  BaseStyle {
public:
    LocalStyle(ShareDataSp charData, ShareDocDataSp docData, const ShareDataMergeMangerSp& shareDataMergeManger):m_charData(shareDataMergeManger->addCacheCharData(charData)), m_docData(docData), m_shareDataMergeManger(shareDataMergeManger){
    }
//    ~LocalStyle() {
//        if(m_shareDataMergeManger.expired()) {
//            return;
//        }
//        auto allocManger = m_shareDataMergeManger.lock();
//        if(!allocManger)
//            return;
//        if(2 == m_charData.use_count())
//            allocManger->removeCharData(m_charData);
//    }
    void setFontSize(float size) {
        m_charData->m_fontSize = size;
    }
    float fontSize() const {
        return m_charData->m_fontSize;
    }
private:
    void setProperty(int type, void* val) override {
        if(PROP_FONT_SIZE == type) {
            auto newVal = *(float*)val;
            auto useCout = m_charData.use_count();
            if(fontSize() == newVal)
                return;
            if(useCout == 2 || useCout == 1) { //自己独占或与内存管理类共享数据
                removeCache(); //更新hash,需先移除
            } else {
                detach(); //创建副本
            }
            setFontSize(newVal);//  改值
            merge();    //缓存更新
        }
    }
    void removeCache() {
        auto allocManger = shareMemoryManger();
        if(!allocManger)
            return;
        allocManger->removeCharData(m_charData); //先删除,key值hash不跟随联动,暂无法解决性能损耗
    }

    void detach() {
        auto allocManger = shareMemoryManger();
        if(!allocManger)
            return;
        m_charData = allocManger->allocCharData(m_charData);
    }

    bool merge() {
        auto allocManger = shareMemoryManger();
        if(!allocManger)
            return false;
        auto cacheCharData = allocManger->addCacheCharData(m_charData); //新数据加入
        if(cacheCharData != m_charData) {
            m_charData = cacheCharData;
            return true;
        } else {
            return false;
        }
    }
private:
    inline ShareDataMergeMangerSp shareMemoryManger() const {
        if(m_shareDataMergeManger.expired())
            return nullptr;
       return m_shareDataMergeManger.lock();
    }
public:
    ShareDataSp m_charData;
    ShareDocDataSp m_docData;
    ShareDataMergeMangerWp m_shareDataMergeManger;
};
using LocalStyleSp = std::shared_ptr<LocalStyle>;

class Style {
public:
    std::string hyperLink;
    int styleId;
    ShareDataSp charData;
};

class DocStyle {
public:
    ShareDocDataSp docData;
    int align;
};

int main(int argc, char** argv)
{
    auto shareDataManger = std::make_shared<ShareDataMergeManger>();
    auto shareCharData = std::make_shared<ShareData>(0);
    auto shareDocData = std::make_shared<ShareDocData>();
    BaseStyleSp localStyle = std::make_shared<LocalStyle>(shareCharData, shareDocData, shareDataManger);
    float size = 1;  //数据存在浮点精度,无法准确去重,暂时不优化
    localStyle->setProperty(BaseStyle::ProperyID::PROP_FONT_SIZE, &size);
    size = 2;
    localStyle->setProperty(BaseStyle::ProperyID::PROP_FONT_SIZE, &size);
    size = 0;
    localStyle->setProperty(BaseStyle::ProperyID::PROP_FONT_SIZE, &size);
    return 0;
}


perf-10万样式-同时修改1万个-5-6ms(堆内存频繁分配,合并,释放,尝试转栈)
#include <iostream>
#include <chrono>
int main(int argc, char** argv)
{
    auto shareDataManger = std::make_shared<ShareDataMergeManger>();
    size_t count = 100000;
    std::vector<BaseStyleSp> vctStyles;
    vctStyles.reserve(count);
    for (int i = 0; i < count; ++i) {
        auto shareCharData = std::make_shared<ShareCharData>(i);
        auto shareDocData = std::make_shared<ShareDocData>();
        BaseStyleSp localStyle = std::make_shared<LocalStyle>(shareCharData, shareDocData, shareDataManger);
        vctStyles.push_back(localStyle);
    }
    // 获取当前时间点
    auto start = std::chrono::high_resolution_clock::now();
    float size = 50000;
    auto shareCharData = std::make_shared<ShareCharData>(size);
    auto shareDocData = std::make_shared<ShareDocData>();
    BaseStyleSp localStyle = std::make_shared<LocalStyle>(shareCharData, shareDocData, shareDataManger);
    for (int i = 40000; i < 50000; ++i) {
         size = i + 1;
         vctStyles.at(i)->setProperty(BaseStyle::ProperyID::PROP_FONT_SIZE, &size);
    }

    // 获取代码执行后的时间点
    auto end = std::chrono::high_resolution_clock::now();
    // 计算代码执行的时间差
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
    // 输出运行时间
    std::cout << "代码执行时间: " << duration << " 微秒" << std::endl;

    return 0;
}
 


创作不易,小小的支持一下吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码力码力我爱你

创作不易,小小的支持一下吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值