0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

可pop任意字節(jié)隊(duì)列代碼的優(yōu)化

冬至子 ? 來(lái)源:技術(shù)鋪?zhàn)?/span> ? 作者:chasenzhang ? 2023-01-18 14:56 ? 次閱讀

前言

主要是對(duì)代碼進(jìn)行了優(yōu)化,優(yōu)化的點(diǎn)有下面幾項(xiàng)

1 對(duì)代碼結(jié)構(gòu)進(jìn)行了調(diào)整。

上次的版本只是一個(gè)簡(jiǎn)單的雛形,這份代碼進(jìn)一步分成了頭文件和實(shí)現(xiàn)文件。

2 優(yōu)化了類(lèi)的封裝性,對(duì)具體實(shí)現(xiàn)進(jìn)行了隱藏。

因?yàn)檫@個(gè)功能是通過(guò)頭結(jié)點(diǎn)的鏈表的實(shí)現(xiàn)的,而在上分代碼中,使用者可以通過(guò)調(diào)用的到頭結(jié)點(diǎn)信息,然后使用者就可以對(duì)這個(gè)鏈表進(jìn)行任意操作,這樣就很危險(xiǎn)。所以在這版中,將所有入口都改成了void *數(shù)據(jù)類(lèi)型,在實(shí)現(xiàn)的地方進(jìn)行類(lèi)型轉(zhuǎn)換,增加了安全性。

具體實(shí)現(xiàn)

頭文件

#include 
#include 
#include 
#include 
#include 


/*
 * MemLink Brief Description
 *
 * link0
 * addr(id, sum, size)->node->node->node->node...
 * 
 * link1
 * addr(id, sum, size)->node->node->node->node...
 * 
 * link2
 * addr(id, sum, size)->node->node->node->node...
 * 
 */


class MemLink
{
public:
    MemLink() { m_mem_link.clear(); }
    ~MemLink() {}


    //create link by id
    int create_link(int id);
    //get link addr, for first para is *addr, !!need to traverse!!
    void *get_addr_by_id(int id);
    //get link addr, for first para is *addr
    void *get_addr_by_index(int index);
    int push_data(void *addr, char *data, int len);
    int read_data(void *addr, char *data, int len);
    int pop_data(void *addr, char *data, int len);


    //delete one link
    int delete_link(void *addr);
    //delete all links
    int delete_memlink();


    //get link description
    int get_id_by_addr(void *addr);
    int get_size_by_addr(void *addr);
    int get_num_by_addr(void *addr);
    int get_memlink_num();
    void printf_memlink_status();


    void link_test();


private:
    std::vector<void *> m_mem_link;


    void *mk_node(int id, char *data, int len);
    int free_node(void *node);
    int push(void *addr, void *node);
    void *pop(void *addr);
    void printf_link(void *addr);   //debug, when data is ascii, can call it
};

實(shí)現(xiàn)文件

#include "test_mem_link.h"


typedef struct Node
{
    int id;     //unique id
    int pos;    //data start pos
    int size;   //data size --> value size = size-pos
    int num;    //for head only
    char *data;
    struct Node *next;
} Node;


void *MemLink::mk_node(int id, char *data, int len)
{
    Node *node = new Node;
    if (node == NULL) {
        perror("new Node failed\\n");
        return NULL;
    }
    if (data != NULL) {
        node->data = new char[len]();
        if (node->data == NULL) {
            perror("node->data = new failed");
            return NULL;
        }
        memcpy(node->data, data, len);
    }
    else node->data = NULL;


    node->id = id;
    node->pos = 0;
    node->size = len;
    node->num = 0;
    node->next = NULL;
    return (void *)node;
}


int MemLink::free_node(void *addr)
{
    Node *node = (Node *)addr;
    if (node->data != NULL)
        delete[] node->data;
    node->data = NULL;
    if (node)
        delete node;
    node = NULL;
    return 0;
}


void *MemLink::get_addr_by_id(int id)
{
    int i = 0;
    for (i = 0; i < (int)m_mem_link.size(); i++) {
        if (id == ((Node *)m_mem_link[i])->id) {
            return (Node *)m_mem_link[i];
        }
    }
    return NULL;
}


int MemLink::create_link(int id)
{
    Node *node_ret = (Node *)get_addr_by_id(id);
    if (node_ret != NULL) {
        printf("link id[%d] exist, can't create it\\n", id);
        return -1;
    }


    printf("link id[%d] not exist, create it\\n", id);
    Node *node = (Node *)mk_node(id, NULL, 0);
    if (node == NULL) {
        printf("mk_node failed!\\n");
    }
    else {
        m_mem_link.push_back((void *)node);
    }


    return 0;
}


int MemLink::push(void *addr, void *node)
{
    Node *p = (Node *)addr;
    while (p->next != NULL) {
        p = p->next;
    }


    ((Node *)node)->next = p->next;
    p->next = ((Node *)node);


    ((Node *)addr)->size += ((Node *)node)->size;
    ((Node *)addr)->num++;
    return 0;
}


int MemLink::get_id_by_addr(void *addr)
{
    return ((Node *)addr)->id;
}
int MemLink::get_size_by_addr(void *addr)
{
    return ((Node *)addr)->size;
}
int MemLink::get_num_by_addr(void *addr)
{
    return ((Node *)addr)->num;
}


int MemLink::push_data(void *addr, char *data, int len)
{
    int id = get_id_by_addr(addr);
    Node *phead = (Node *)addr;
    Node *node = (Node *)mk_node(id, data, len);
    if (node == NULL) {
        printf("mk_node failed!\\n");
    }
    push(phead, node);
}


void *MemLink::pop(void *addr)
{
    Node *p = ((Node *)addr)->next;
    if (p != NULL) {
        ((Node *)addr)->size -= p->size - p->pos;
        ((Node *)addr)->next = p->next;
        ((Node *)addr)->num--;
        p->next = NULL;
        return p;
    }
    return NULL;
}


void *MemLink::get_addr_by_index(int index)
{
    return m_mem_link[index];
}


int MemLink::read_data(void *addr, char *data, int len)
{
    Node *phead = (Node *)addr;
    if (len > phead->size) {
        printf("pop data len > link size, read data failed\\n");
        return -1;
    }


    int i_read = 0;
    Node *p = phead->next;
    while (1) {
        if (p == NULL) {
            printf("p == NULL\\n");
            break;
        }


        if (i_read + p->size - p->pos > len) {
            //printf(" < len\\n");
            memcpy(&data[i_read], &p->data[p->pos], len - i_read);
            break;
        }


        if (i_read + p->size - p->pos == len) {
            //printf(" = len\\n");
            memcpy(&data[i_read], &p->data[p->pos], p->size - p->pos);
            break;
        }


        if (i_read + p->size - p->pos < len) {
            //printf(" > len\\n");
            memcpy(&data[i_read], &p->data[p->pos], p->size - p->pos);
            i_read += p->size - p->pos;
            p = p->next;
        }
    }
    return 0;
}


int MemLink::pop_data(void *addr, char *data, int len)
{
    Node *phead = (Node *)addr;
    if (len > phead->size) {
        printf("pop data len > link size, read data failed\\n");
        return -1;
    }


    Node *phead_tmp = phead;
    int i_read = 0;
    while (1) {
        Node *p = phead_tmp->next;
        if (p == NULL) {
            printf("p == NULL\\n");
            break;
        }


        if (i_read + p->size - p->pos > len) {
            // printf(" > len\\n");
            memcpy(&data[i_read], &p->data[p->pos], len - i_read);


            p->pos += len - i_read;
            phead->size -= len - i_read;
            break;
        }


        if (i_read + p->size - p->pos == len) {
            // printf(" = len\\n");
            memcpy(&data[i_read], &p->data[p->pos], p->size - p->pos);


            phead->size -= p->size - p->pos;
            phead_tmp->next = p->next;
            phead->num--;
            free_node(p);
            p = NULL;
            break;
        }


        if (i_read + p->size - p->pos < len) {
            // printf(" < len\\n");
            memcpy(&data[i_read], &p->data[p->pos], p->size - p->pos);
            i_read += p->size - p->pos;


            phead->size -= p->size - p->pos;
            phead_tmp->next = p->next;
            phead->num--;
            free_node(p);
            p = NULL;
        }
    }
    return 0;
}


int MemLink::get_memlink_num()
{
    return m_mem_link.size();
}


void MemLink::printf_memlink_status()
{
    int i = 0;
    for (i = 0; i < (int)m_mem_link.size(); i++) {
        Node *phead = (Node *)m_mem_link[i];
        printf(">link: id: %d, pos: %d, num: %d, size: %d, data: %s\\n", phead->id,
                            phead->pos, phead->num, phead->size, phead->data);
    }
}


void MemLink::printf_link(void *addr)
{
    Node *phead = (Node *)addr;
    printf(">link: id: %d, pos: %d, num: %d, size: %d, data: %s\\n", phead->id,
                        phead->pos, phead->num, phead->size, phead->data);
    Node *p = phead->next;
    while (p) {
        printf("node:  id: %d, pos: %d, size: %d\\n", p->id, p->pos, p->size);
        p = p->next;
    }
}


int MemLink::delete_link(void *addr)
{
    int id = get_id_by_addr(addr);
    Node *phead = (Node *)addr;
    Node *p = phead->next;
    while (phead->next) {
        p = phead->next;
        phead->next = p->next;
        free_node(p);
    }


    std::vector<void *>::iterator it;
    for (it = m_mem_link.begin(); it != m_mem_link.end(); ) {
        //if (((Node *)it)->id == get_id_by_addr(addr)))
        if (*it == addr) {
            //printf("%d = %d\\n", get_id_by_addr(*it), get_id_by_addr(addr));
            it = m_mem_link.erase(it);
            break;
        }
        else it++;
    }


    free_node(phead);
    printf("delete id[%d] link\\n", id);


    return 0;
}


int MemLink::delete_memlink()
{
    int i = 0;
    for (i = 0; i < (int)m_mem_link.size(); i++) {
        int id = get_id_by_addr(m_mem_link[i]);
        Node *phead = (Node *)m_mem_link[i];
        Node *p = phead->next;
        while (phead->next) {
            p = phead->next;
            phead->next = p->next;
            free_node(p);
        }
        printf("delete id[%d] link\\n", id);
        free_node(phead);
    }
    m_mem_link.clear();
    return 0;
}


void MemLink::link_test()
{
    int id = 10;
    create_link(id);


    // push
    char tmp[10] = {0};
    void *addr = get_addr_by_id(id);
    strcpy(tmp, "111222333");
    push_data(addr, tmp, strlen(tmp));
    strcpy(tmp, "444555666");
    push_data(addr, tmp, strlen(tmp));
    strcpy(tmp, "777888999");
    push_data(addr, tmp, strlen(tmp));


    push_data(addr, (char *)"1", strlen("1"));
    push_data(addr, (char *)"2", strlen("2"));
    push_data(addr, (char *)"3", strlen("3"));
    push_data(addr, (char *)"4", strlen("4"));
    push_data(addr, (char *)"5", strlen("5"));
    push_data(addr, (char *)"6", strlen("6"));
    push_data(addr, (char *)"7", strlen("7"));


    id = 20;
    create_link(id);
    addr = get_addr_by_id(id);
    push_data(addr, (char *)"8", strlen("8"));
    push_data(addr, (char *)"9", strlen("9"));
    push_data(addr, (char *)"10", strlen("10"));


    id = 30;
    create_link(id);
    addr = get_addr_by_id(id);
    push_data(addr, (char *)"11", strlen("11"));
    push_data(addr, (char *)"12", strlen("12"));
    push_data(addr, (char *)"13", strlen("13"));




    printf_memlink_status();
    int memlink_num = get_memlink_num();
    printf("\\nmemlink_num = %d\\n", memlink_num);
    for (int i = 0; i < memlink_num; i++) {
        void *addr = get_addr_by_index(i);
        // printf_link(addr);
        if (get_id_by_addr(addr) == 10) {
            // //pop
            // Node *p4 = pop(phead);
            // printf("pop size = %d\\n", p4->size);
            // free_node(p4);


            char read_tmp[11 + 1] = {0};
            pop_data(addr, read_tmp, 11);
            printf("read_data = %s\\n", read_tmp);


            char read_tmp2[8 + 1] = {0};
            pop_data(addr, read_tmp2, 8);
            printf("read_data = %s\\n", read_tmp2);
            // printf_link(addr);
        }
    }


    addr = get_addr_by_id(20);
    delete_link(addr);


    delete_memlink();
}


int main()
{
    MemLink ml;
    ml.link_test();


    return 0;
}

審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • printf函數(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    31

    瀏覽量

    5871
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Freertos隊(duì)列項(xiàng)里的字節(jié)長(zhǎng)度是否可以獲取?

    最近剛學(xué)Freertos, 看到可以獲取Freertos隊(duì)列長(zhǎng)度,但是隊(duì)列項(xiàng)里的字節(jié)長(zhǎng)度是否可以獲?。? 因?yàn)轫?xiàng)目中隊(duì)列中會(huì)存放不定長(zhǎng)字節(jié),
    發(fā)表于 04-29 07:17

    【MiCOKit試用體驗(yàn)】慶科MiCO系統(tǒng)篇(4)MiCO RTOS消息隊(duì)列

    , uint32_tnumber_of_messages );該函數(shù)為初始化一個(gè)消息隊(duì)列,參數(shù)1為指向要初始化的消息隊(duì)列的句柄指針;參數(shù)2為消息隊(duì)列的名稱(chēng),由用戶(hù)定義;參數(shù)3為將要進(jìn)入隊(duì)列
    發(fā)表于 10-24 17:03

    keystoneII arm示例程序網(wǎng)卡中斷,請(qǐng)問(wèn)隊(duì)列收到包后,如果暫時(shí)不從隊(duì)列pop包,是否可以在隊(duì)列這個(gè)級(jí)別清除中斷信號(hào)?

    描述:目前開(kāi)發(fā)板示例程序網(wǎng)卡驅(qū)動(dòng)中,接收用了queue-658,這個(gè)隊(duì)列的中斷信號(hào)直接給了中斷控制器,請(qǐng)問(wèn),如果隊(duì)列收到包后,如果暫時(shí)不從隊(duì)列pop包的話(huà),是否可以在
    發(fā)表于 08-03 07:43

    ARM Artisan物聯(lián)網(wǎng)POP IP是什么?

    ;*** CryptoCell技術(shù)有助于強(qiáng)化安全SoC設(shè)計(jì);采用ARM Cordio? radio IP的完整無(wú)線(xiàn)解決方案,支持802.15.4 和Bluetooth? 5;通過(guò)ARM mbed? Cloud,云服務(wù)能夠支持物聯(lián)網(wǎng)設(shè)備的安全管理;ARM Artisan? IoT POP IP針對(duì)臺(tái)積電40ULP工藝
    發(fā)表于 10-23 08:21

    STM32使用靜態(tài)隊(duì)列保存數(shù)據(jù) 精選資料分享

    最近在調(diào)試CAN總線(xiàn)接口的BootLoader。由于應(yīng)用程序的代碼比較大,升級(jí)過(guò)程比較慢。所以在不斷的優(yōu)化BootLoader程序,讓升級(jí)時(shí)間盡可能縮短。其中最重要的就是使用了隊(duì)列,而且使用的是靜態(tài)
    發(fā)表于 08-20 06:02

    為什么要使用消息隊(duì)列?消息隊(duì)列的優(yōu)缺點(diǎn)

    優(yōu)化:?jiǎn)栴}1:為什么要使用消息隊(duì)列?問(wèn)題2:消息隊(duì)列的優(yōu)缺點(diǎn)?問(wèn)題3:如何增強(qiáng)消息隊(duì)列使用的穩(wěn)定性?問(wèn)題1:為什么會(huì)使用消息隊(duì)列?由于業(yè)務(wù)劃
    發(fā)表于 12-22 06:28

    循環(huán)隊(duì)列的實(shí)用代碼的應(yīng)用方式

    循環(huán)隊(duì)列的實(shí)用代碼概念就不過(guò)多說(shuō)明,直接上干貨,不好的地方請(qǐng)多擔(dān)待指正。功能說(shuō)明:用一個(gè)藍(lán)牙模塊,利用串口接收/發(fā)送中斷,接收數(shù)據(jù),發(fā)送數(shù)據(jù)的例子(注:如果要直接套用代碼,那發(fā)送中斷的模式必須設(shè)置為發(fā)送完成后中斷。即發(fā)送一個(gè)
    發(fā)表于 01-21 07:26

    簡(jiǎn)單羅列幾種隊(duì)列管理邏輯電路

    方式,比如移位寄存器。使用SpinalHDL實(shí)現(xiàn)FIFO的代碼如下。輸入輸出的push/pop,使用了valid/ready握手的Stream接口;使用Mem定義環(huán)形buffer,pushPtr
    發(fā)表于 08-29 14:23

    什么是PoP

    什么是PoP  英文縮寫(xiě): PoP 中文譯名: 接入點(diǎn) 分  類(lèi): IP與多媒體
    發(fā)表于 02-23 09:41 ?1748次閱讀

    POP3協(xié)議和Base 64編碼原理

    POP3適用于C/S結(jié)構(gòu)的脫機(jī)模型,是因特網(wǎng)電子郵件的第一個(gè)離線(xiàn)協(xié)議標(biāo)準(zhǔn),Base 64是一種很常見(jiàn)的編碼規(guī)范,被設(shè)計(jì)用來(lái)將任意序列的8字節(jié)描述為一種不易被人直接識(shí)別的形式
    發(fā)表于 01-12 19:08 ?2141次閱讀
    <b class='flag-5'>POP</b>3協(xié)議和Base 64編碼原理

    淺談鴻蒙內(nèi)核代碼調(diào)度隊(duì)列

    鴻蒙內(nèi)核代碼中有兩個(gè)源文件是關(guān)于隊(duì)列的,一個(gè)是用于調(diào)度的隊(duì)列,另一個(gè)是用于線(xiàn)程間通訊的IPC隊(duì)列
    的頭像 發(fā)表于 10-23 11:00 ?1968次閱讀

    RTOS消息隊(duì)列的多種用途

      消息隊(duì)列可以以多種不同的方式使用。事實(shí)上,您可以編寫(xiě)可能只使用消息隊(duì)列的相當(dāng)復(fù)雜的應(yīng)用程序。僅使用消息隊(duì)列可以減少代碼的大?。凑加每臻g),因?yàn)榭梢阅M許多其他服務(wù)(信號(hào)量、時(shí)間延
    的頭像 發(fā)表于 06-29 14:57 ?2428次閱讀
    RTOS消息<b class='flag-5'>隊(duì)列</b>的多種用途

    pop任意字節(jié)隊(duì)列

    在一般的鏈表中,數(shù)據(jù)是存儲(chǔ)在node節(jié)點(diǎn)中的,每次pop出來(lái)的數(shù)據(jù)是以node為單位的。這篇文章,我們對(duì)一般的鏈表進(jìn)行改進(jìn),可以pop任意字節(jié)的數(shù)據(jù),
    的頭像 發(fā)表于 01-18 15:02 ?787次閱讀
    <b class='flag-5'>可</b><b class='flag-5'>pop</b><b class='flag-5'>任意</b><b class='flag-5'>字節(jié)</b>的<b class='flag-5'>隊(duì)列</b>

    RTOS消息隊(duì)列的應(yīng)用

    基于RTOS的應(yīng)用中,通常使用隊(duì)列機(jī)制實(shí)現(xiàn)任務(wù)間的數(shù)據(jù)交互,一個(gè)應(yīng)用程序可以有任意數(shù)量的消息隊(duì)列,每個(gè)消息隊(duì)列都有自己的用途。
    發(fā)表于 05-29 10:49 ?581次閱讀
    RTOS消息<b class='flag-5'>隊(duì)列</b>的應(yīng)用

    MCU專(zhuān)屬隊(duì)列功能模塊之QueueForMcu應(yīng)用

    當(dāng)需要從隊(duì)列頭部獲取多個(gè)數(shù)據(jù),但又不希望數(shù)據(jù)從隊(duì)列中刪除時(shí),可以使用 Queue_Peek_Array 函數(shù)來(lái)實(shí)現(xiàn),該函數(shù)的參數(shù)與返回值與 Queue_Pop_Array 完全相同。
    發(fā)表于 03-20 11:44 ?368次閱讀
    MCU專(zhuān)屬<b class='flag-5'>隊(duì)列</b>功能模塊之QueueForMcu應(yīng)用