#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;
}
队列多线程push单线程pop的场景
最新推荐文章于 2024-05-27 16:53:08 发布