【C语言手写并发容器】concurrent_vector & concurrent_queue

这是C语言手写高性能并发容器系列第一篇。由于在微软实习的任务一个月就做完了。故自己找点事情做。

没啥难的。只是用 C 自己写了大家都懂的一些机制。
自动扩容,支持并发访问。提供了如下的操作方法。

#pragma once
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#define INIT_SIZE 4

typedef struct con_vector {
    void** data;
    size_t cap;
    size_t tail;
    pthread_spinlock_t lock;
}con_vector;

// constructor
con_vector* create_vector() {
    con_vector* ret = malloc(sizeof(con_vector));
    ret->cap = (1 << INIT_SIZE);
    ret->data = malloc(sizeof(void*) * ret->cap);
    ret->tail = 0;
    pthread_spin_init(&ret->lock, PTHREAD_PROCESS_PRIVATE);
    return ret;
}

// auto-expansion, DO NOT CALL MANNUALLY
void resize(con_vector* s) {
    s->cap <<= 1;
    void** old = s->data;
    s->data = malloc(sizeof(void*) * s->cap);
    memcpy(s->data, old, sizeof(void*) * s->tail);
    free(old);
}

// push an item to the back
void push_back(con_vector* s, void* val) {
    pthread_spin_lock(&s->lock);
    if(s->tail == s->cap) {
        resize(s);
    }
    s->data[s->tail ++] = val;
    pthread_spin_unlock(&s->lock);
}

// pop and return the last item, if data is empty, return NULL
void* pop_back(con_vector* s) {
    pthread_spin_lock(&s->lock);
    if(s->tail == 0) {
        pthread_spin_unlock(&s->lock);
        return NULL;
    }
    void* ret = s->data[-- s->tail];
    pthread_spin_unlock(&s->lock);
    return ret;
}

// get the value of vector[i], reuturn NULL if i is out or range
void* get(con_vector* s, size_t i) {
    pthread_spin_lock(&s->lock);
    if(i < 0 || i >= s->tail) {
        pthread_spin_unlock(&s->lock);
        return NULL;
    }
    void* ret = s->data[i];
    pthread_spin_unlock(&s->lock);
    return ret;
}

// set the value of vector[i], return false if i is out of range
bool set(con_vector* s, size_t i, void* val) {
    pthread_spin_lock(&s->lock);
    if(i < 0 || i >= s->tail) {
        pthread_spin_unlock(&s->lock);
        return false;
    }
    s->data[i] = val;
    pthread_spin_unlock(&s->lock);
    return true;
}

// return the size of the vector
size_t size(con_vector* s) {
    return s->tail - 1;
}

// quicksort
void sort(con_vector*s, void* cmp) {
    pthread_spin_lock(&s->lock);
    qsort(s->data, s->tail, sizeof(void*), cmp);
    pthread_spin_unlock(&s->lock);
}

#pragma once
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#define INIT_SIZE 4

typedef struct con_queue {
    void** data;
    size_t cap;
    size_t head;
    size_t tail;
    pthread_spinlock_t lock;
}con_queue;

// constructor
con_queue* create_queue() {
    con_queue* ret = malloc(sizeof(con_queue));
    ret->cap = (1 << INIT_SIZE) - 1;
    ret->data = malloc(sizeof(void*) * (ret->cap + 1));
    ret->head = 0;
    ret->tail = 0;
    pthread_spin_init(&ret->lock, PTHREAD_PROCESS_PRIVATE);
    return ret;
}

// auto-expansion, DO NOT CALL MANNUALLY
void resize(con_queue* s) {
    s->cap = (s->cap << 1) | 1;
    void** old = s->data;
    s->data = malloc(sizeof(void*) * (s->cap + 1));
    if(s->head <= s->tail) {
        memcpy(s->data, &old[s->head], sizeof(void*) * (s->tail - s->head));
        s->tail -= s->head;
    } else {
        size_t fr = (s->cap >> 1) + 1 - s->head;
        memcpy(s->data, &old[s->head], sizeof(void*) * fr);
        memcpy(&s->data[fr], old, sizeof(void*) * s->tail);
        s->tail += fr;
    }
    s->head = 0;
    free(old);
}

// push an item to the back
void push(con_queue* s, void* val) {
    pthread_spin_lock(&s->lock);
    size_t nxt = (s->tail + 1) & s->cap;
    if(nxt == s->head) {
        resize(s);
        nxt = s->tail + 1;
    }
    s->data[s->tail] = val;
    s->tail = nxt;
    pthread_spin_unlock(&s->lock);
}

// pop and return an item from the front, return NULL if queue is empty
void* pop(con_queue* s) {
    pthread_spin_lock(&s->lock);
    if(s->tail == s->head) {
        pthread_spin_unlock(&s->lock);
        return NULL;
    }
    void* ret = s->data[s->head];
    s->head = (s->head + 1) & s->cap;
    pthread_spin_unlock(&s->lock);
    return ret;
}
// return the item from the front, return NULL if queue is empty
void* top(con_queue* s) {
    pthread_spin_lock(&s->lock);
    if(s->head == s->tail) {
        pthread_spin_unlock(&s->lock);
        return NULL;
    }
    void* ret = s->data[s->head];
    pthread_spin_unlock(&s->lock);
    return ret;
}

// return the size of the queue
size_t size(con_queue* s) {
    pthread_spin_lock(&s->lock);
    if(s->head <= s->tail) {
        pthread_spin_unlock(&s->lock);
        return s->tail - s->head;
    } else {
        pthread_spin_unlock(&s->lock);
        return s->tail + s->cap + 1 - s->head;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值