Source code analysis of spool — swbuffer of memory module

Time:2021-1-17

preface

swooleReceiving and sending of data (e.greactorThe thread accepts the client message, sends the message to the client, receives the message from the clientworkerMessage to send toworkerThe buffer is involved,swooleThe buffer implementation in isswBufferIt’s actually a single linked list.

swBufferData structure of

  • swBufferIn data structuretrunk_numIs the number of linked list elements,trunk_sizeyesswBufferWhen the buffer is created, the specified size of the linked list element (the actual size is not necessarily this value),lengthIs the total amount of memory actually occupied by the buffer.
  • swBuffer_trunkIntypeThere are three scenarios: caching data, sending files and reminding the connection to close.lengthRefers to the memory size of the element.
enum swBufferChunk
{
    SW_CHUNK_DATA,
    SW_CHUNK_SENDFILE,
    SW_CHUNK_CLOSE,
};

typedef struct _swBuffer_trunk
{
    uint32_t type;
    uint32_t length;
    uint32_t offset;
    union
    {
        void *ptr;
        struct
        {
            uint32_t val1;
            uint32_t val2;
        } data;
    } store;
    uint32_t size;
    void (*destroy)(struct _swBuffer_trunk *chunk);
    struct _swBuffer_trunk *next;
} swBuffer_trunk;

typedef struct _swBuffer
{
    int fd;
    uint8_ t trunk_ Num; // number of trunk
    uint16_t trunk_size;
    uint32_t length;
    swBuffer_trunk *head;
    swBuffer_trunk *tail;
} swBuffer;

swBufferCreation of

swBufferThe creation of is simple, just initializing the entire systemswBufferOfheaderHead element only:

swBuffer* swBuffer_new(int trunk_size)
{
    swBuffer *buffer = sw_malloc(sizeof(swBuffer));
    if (buffer == NULL)
    {
        swWarn("malloc for buffer failed. Error: %s[%d]", strerror(errno), errno);
        return NULL;
    }

    bzero(buffer, sizeof(swBuffer));
    buffer->trunk_size = trunk_size;

    return buffer;
}

swBufferMemory application

swBufferMemory application logic is also very simple, according to the incomingsizeParameters apply memory for linked list elements, initialize member variables, and then put linked list elements at the end of the linked list

int swBuffer_append(swBuffer *buffer, void *data, uint32_t size)
{
    swBuffer_trunk *chunk = swBuffer_new_trunk(buffer, SW_CHUNK_DATA, size);
    if (chunk == NULL)
    {
        return SW_ERR;
    }

    buffer->length += size;
    chunk->length = size;

    memcpy(chunk->store.ptr, data, size);

    swTraceLog(SW_TRACE_BUFFER, "trunk_n=%d|size=%d|trunk_len=%d|trunk=%p", buffer->trunk_num, size,
            chunk->length, chunk);

    return SW_OK;
}

swBuffer_trunk *swBuffer_new_trunk(swBuffer *buffer, uint32_t type, uint32_t size)
{
    swBuffer_trunk *chunk = sw_malloc(sizeof(swBuffer_trunk));
    if (chunk == NULL)
    {
        swWarn("malloc for trunk failed. Error: %s[%d]", strerror(errno), errno);
        return NULL;
    }

    bzero(chunk, sizeof(swBuffer_trunk));

    //require alloc memory
    if (type == SW_CHUNK_DATA && size > 0)
    {
        void *buf = sw_malloc(size);
        if (buf == NULL)
        {
            swWarn("malloc(%d) for data failed. Error: %s[%d]", size, strerror(errno), errno);
            sw_free(chunk);
            return NULL;
        }
        chunk->size = size;
        chunk->store.ptr = buf;
    }

    chunk->type = type;
    buffer->trunk_num ++;

    if (buffer->head == NULL)
    {
        buffer->tail = buffer->head = chunk;
    }
    else
    {
        buffer->tail->next = chunk;
        buffer->tail = chunk;
    }

    return chunk;
}

obtainswBufferThe elements of

fromswBufferThe buffer can only get data fromheadFrom the

#define swBuffer_get_trunk(buffer)   (buffer->head)

swBufferElementalpop

After getting the elements of the buffer, delete them accordinglyheadLinked list element:

void swBuffer_pop_trunk(swBuffer *buffer, swBuffer_trunk *chunk)
{
    if (chunk->next == NULL)
    {
        buffer->head = NULL;
        buffer->tail = NULL;
        buffer->length = 0;
        buffer->trunk_num = 0;
    }
    else
    {
        buffer->head = chunk->next;
        buffer->length -= chunk->length;
        buffer->trunk_num--;
    }
    if (chunk->type == SW_CHUNK_DATA)
    {
        sw_free(chunk->store.ptr);
    }
    if (chunk->destroy)
    {
        chunk->destroy(chunk);
    }
    sw_free(chunk);
}

swBufferDestruction of buffer

int swBuffer_free(swBuffer *buffer)
{
    volatile swBuffer_trunk *chunk = buffer->head;
    void * *will_free_trunk;  //free the point
    while (chunk != NULL)
    {
        if (chunk->type == SW_CHUNK_DATA)
        {
            sw_free(chunk->store.ptr);
        }
        will_free_trunk = (void *) chunk;
        chunk = chunk->next;
        sw_free(will_free_trunk);
    }
    sw_free(buffer);
    return SW_OK;
}

Recommended Today

DK7 switch’s support for string

Before JDK7, switch can only support byte, short, char, int or their corresponding encapsulation classes and enum types. After JDK7, switch supports string type. In the switch statement, the value of the expression cannot be null, otherwise NullPointerException will be thrown at runtime. Null cannot be used in the case clause, otherwise compilation errors will […]