队列多线程push单线程pop的场景

#ifndef Linux
#include <windows.h>
#include <winnt.h>
#endif // !Linux

#include <iostream>
#include <string>
#include <thread>
#include <queue>
#include <array>
#include <assert.h>
#include <sstream>

#ifdef Linux
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#else
#include <mutex>
#define usleep(n) Sleep(n) 
#endif

#ifdef Linux
class spin_lock
{
public:
    spin_lock()
    {
        pthread_spin_init(&_lock, PTHREAD_PROCESS_PRIVATE);
    }
    void lock()
    {
        pthread_spin_lock(&_lock);
    }
    void unlock()
    {
        pthread_spin_unlock(&_lock);
    }
private:
    pthread_spinlock_t  _lock;
};

#else
/* Has not tuned performance on Windows.
 */
class spin_lock
{
public:
    spin_lock()
    {}
    void lock()
    {
        _mutex.lock();
    }
    void unlock()
    {
        _mutex.unlock();
    }
private:
    std::mutex _mutex;
};
#endif

class auto_lock
{
public:
    auto_lock(spin_lock* lock)
    {
        _lock = lock;
        _lock->lock();
    }

    ~auto_lock()
    {
        _lock->unlock();
    }
private:
    spin_lock* _lock;
};



using namespace std;

struct ttt
{
    char a[124];
    int b;
};

#ifdef Linux
#define smp_rmb()    asm volatile("lfence":::"memory")
#define smp_mb()    asm volatile("mfence":::"memory")
#define smp_wmb()    asm volatile("sfence" ::: "memory")
#else
#define smp_rmb()  MemoryBarrier()
#define smp_mb()   MemoryBarrier()
#define smp_wmb()  MemoryBarrier()
#endif

template <typename T>
class CCycleQueueAbyss {
public:
    // 构造函数
    CCycleQueueAbyss(int size = 1000000)
    {
        assert(1000000 >= size);
        m_nSize = size;
        w = 0;
        r = 0;
    }

    bool empty(void)
    {
        return w == r;
    }

    int size(void)
    {
        if (w < r)
        {
            return w + m_nSize - r;
        }
        else
        {
            return w - r;
        }
    }

    T pop(void)
    {
        while (r == w);
        if (w - r > m_nSize)
        {
            r = w - 1;
        }
        smp_rmb();
        return m_array[(r++) % m_nSize];
    }

    bool try_pop(T& a)
    {
        if (r != w)
        {
            if (w - r > m_nSize)
            {
                r = w - 1;
            }
            smp_rmb();
            a = m_array[(r++) % m_nSize];
            return true;
        }
        return false;
    }

    bool try_pop(T** a)
    {
        if (r != w)
        {
            if (w - r > m_nSize)
            {
                r = w - 1;
            }
            smp_rmb();
            *a = m_array[(r++) % m_nSize];
            return true;
        }
        return false;
    }

    void push(const T& a)
    {
        m_array[w % m_nSize] = a;
        smp_wmb();
        ++w;
    }

private:
    std::array<T, 1000000> m_array;  // 最大容量是10000
    long long r; // r == w 表示空     w - r > m_nSize 表示溢出了
    long long w;
    int m_nSize;
};


template <typename T>
struct CQueueItem
{
    long long id;
    CCycleQueueAbyss<T>* item;
};

template <typename T>
class CMultiCycleQueue {
public:
    // 构造函数
    CMultiCycleQueue(int nSize = 100) // 线程数
    {
        qItem = new CQueueItem<T>[nSize] {};
        m_index = 0;
    }

    ~CMultiCycleQueue(void)
    {
        delete[]qItem;
    }

    T pop(void)
    {
        while (true)
        {
            for (int i = 0; i < m_index; ++i)
            {
                if (!qItem[i].item->empty())
                {
                    return qItem[i].item->pop();
                }
            }
        }
    }

    bool empty()
    {
        for (int i = 0; i < m_index; ++i)
        {
            if (!qItem[i].item.empty())
            {
                return false;
            }
        }
        return true;
    }


    int size()
    {
        int n = 0;
        for (int i = 0; i < m_index; ++i)
        {
            if (!qItem[i].item.empty())
            {
                n += qItem[i].item.size();
            }
        }
        return n;
    }

    bool try_pop(T& a)
    {
        for (int i = 0; i < m_index; ++i)
        {
            if (!qItem[i].item.empty())
            {
                return qItem[i].item->try_pop(a);
            }
        }
        return false;
    }

    bool try_pop(T& a, long long& pid)
    {
        for (int i = 0; i < m_index; ++i)
        {
            int i_step = (i + m_nStep++) % m_index;
            if (qItem[i_step].item->try_pop(a))
            {
                pid = qItem[i_step].id;
                return true;
            }
        }
        return false;
    }

    bool try_pop(T** a, long long& pid)
    {
        for (int i = 0; i < m_index; ++i)
        {
            int i_step = (i + m_nStep++) / m_index;
            if (qItem[i_step].item->try_pop(a))
            {
                pid = qItem[i_step].id;
                return true;
            }
        }
        return false;
    }

    T pop(long long& id)
    {
        while (true)
        {
            for (int i = 0; i < m_index; ++i)
            {
                if (!qItem[i].item.empty())
                {
                    id = qItem[i].id;
                    return qItem[i].item.pop();
                }
            }
        }
    }

    void pop(T& a)
    {
        for (int i = 0; i < m_index; ++i)
        {
            if (!qItem[i].empty())
            {
                qItem[i].item.pop(a);
            }
        }
    }

    bool push(const T& a)
    {
        std::ostringstream   oss;
        oss << std::this_thread::get_id();
        std::string str = oss.str();
        //std::cout << "thread_push:  " << str << std::endl;
        long long id = atoll(str.c_str());
        for (int i = 0; i < m_index; ++i)
        {
            if (qItem[i].id == id)
            {
                qItem[i].item->push(a);
                return true;
            }
        }
        auto_lock lock(&m_lock); // 这里要加锁,避免多个线程同时创建
        qItem[m_index].id = id;
        qItem[m_index].item = new CCycleQueueAbyss<T>();
        qItem[m_index].item->push(a);
        smp_wmb();
        m_index = m_index + 1;
        return true;
    }

    bool try_push(const T& a)
    {
        std::ostringstream   oss;
        oss << std::this_thread::get_id();
        std::string str = oss.str();
        long long id = atoll(str.c_str());
        for (int i = 0; i < m_index; ++i)
        {
            if (qItem[i].id == id)
            {
                return qItem[i]->item.try_push(a);
            }
        }
        auto_lock lock(&m_lock); // 这里要加锁,避免多个线程同时创建
        qItem[m_index].id = id;
        qItem[m_index].item = new CCycleQueueAbyss<T>();
        qItem[m_index].item->push(a);
        smp_wmb();
        m_index = m_index + 1;
        return true;
    }

private:
    long long m_nStep;
    int m_index;
    CQueueItem<T>* qItem;
    spin_lock m_lock;
};

CMultiCycleQueue<ttt*> q;
void f()
{
    while (1)
    {
        ttt *p = NULL;
        long long pid;
        if (q.try_pop(p, pid))
        {
            cout << "pid:" << pid << "\tn:" << p->b << "\n";
        }
    }
}

void f_push_data()
{
    for (int i = 0; ; ++i)
    {
        static ttt* t = new ttt();
        t->b = i;
        //usleep(1);
        q.push(t);
    }
}

int main()
{

    static auto t = thread(f);
    static auto t_p = thread(f_push_data);
    static auto t_p2 = thread(f_push_data);
    static auto t_p3 = thread(f_push_data);
    static auto t_p4 = thread(f_push_data);
    for (int i = 0; ; ++i)
    {
        static ttt* t = new ttt();
        t->b = i;
        //usleep(1);
        q.push(t);
    }
    //t_p.join();
    t.join();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值