Segment成员变量

long long m_index;

记录该segment的索引号。

int* volatile m_state;

状态数组,标识所对应的元素节点的状态,默认值为0,如果该元素节点添加了值,则标记为1。

T* volatile m_array;

队列元素存储空间的指针。

Segment* volatile m_next;

指向下一个segment的指针。

volatile long m_high;

标识在当前segment,元素最后添加的索引值,初始值为-1,如果该segment被填满了,则该值为SEGMENT_SIZE – 1。

volatile long m_low;

标识在当前segment,元素最后取出位置的索引值,初始值为0,如果该segment一个都没有取走元素,则该值为0。如果m_low >m_high,表示该segment为空。

Segment成员函数

void Grow(Segment* volatile* tail)

1
2
3
4
5
6
void Grow(Segment* volatile* tail)
{
    Segment* segment = new Segment(m_index + 1);
    m_next = segment;
    *tail = m_next;
}
1
创建下一个segment,并将tail指针指向新创建的segment;

bool TryAppend(T value, Segment* volatile *  tail)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool TryAppend(T value, Segment* volatile *  tail)
{
    if (m_high >= SEGMENT_SIZE - 1)
    {
        return false;
    }
 
    int index = SEGMENT_SIZE;
 
    index = InterlockedIncrement(&m_high);
 
    if (index <= SEGMENT_SIZE - 1)
    {
        m_array[index] = value;
        m_state[index] = 1;
    }
    if (index == SEGMENT_SIZE - 1)
    {
        Grow(tail);
    }
     
    return (index <= SEGMENT_SIZE - 1);
}

往当前segment里面,增加一个元素,如果添加满了,就创建下一个segment。

bool TryPeek(T* result)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool TryPeek(T* result)
{
    int low = GetLow();
    if (low > GetHigh())
    {
        return false;
    }
 
    DNetSpinWait wait;
    while (m_state[low] == 0)
    {
        wait.SpinOnce();
    }
    *result = m_array[low];
    return true;
}

如果segment为空,返回false,否则,返回low所在位置的值。

bool TryRemove(T* result, Segment* volatile * head)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
bool TryRemove(T* result, Segment* volatile * head)
{
    DNetSpinWait wait;
    int low = GetLow();
    for (int i = GetHigh(); low <= i; i = GetHigh())
    {
        if (InterlockedCompareExchange(&m_low, low + 1, low) == low)
        {  
 
            DNetSpinWait wait2;
            while (m_state[low] == 0)
            {
                wait2.SpinOnce();
            }
            *result = m_array[low];
            if ((low + 1) >= SEGMENT_SIZE)
            {
                wait2.Reset();
                while (m_next == NULL)
                {
                    wait2.SpinOnce();
                }
                *head = m_next;
            }
            return true;
        }
        wait.SpinOnce();
        low = GetLow();
    }
    result = NULL;
    return false;
}

这是最复杂的一个方法。利用了InterlockedCompareExchange方法,该方法的解释:
LONG __cdecl InterlockedCompareExchange(
  __inout  LONG volatile* Destination,
  __in     LONG Exchange,
  __in     LONG Comparand
);
Parameters
Destination 
A pointer to the destination value. The sign is ignored.

Exchange 
The exchange value. The sign is ignored.

Comparand 
The value to compare to Destination. The sign is ignored.

Return Value
The function returns the initial value of the Destination parameter.

通过自旋来保证线程同步。

int GetHigh()


    return min(m_high, SEGMENT_SIZE - 1);
}

bool IsEmpty()

{
    return m_low > m_high;
}

int GetLow()


    return min(m_low, SEGMENT_SIZE);
}

Segment* GetNext()

{
    return m_next;
}

long long GetIndex()

{
    return m_index;
}

c# 高效的线程安全队列ConcurrentQueue(下) Segment类的更多相关文章

  1. c# 高效的线程安全队列ConcurrentQueue

    c#高效的线程安全队列ConcurrentQueue<T>(上) c# 高效的线程安全队列ConcurrentQueue(下) Segment类 c#高效的线程安全队列Concurrent ...

  2. c#高效的线程安全队列ConcurrentQueue<T>(上)

      ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数 ...

  3. C#数据结构-线程安全队列

    什么是线程安全? 答:线程安全是多线程编程时的计算机程序代码中的一个概念.在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意 ...

  4. C#-----线程安全的ConcurrentQueue<T>队列

     ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数据 ...

  5. 线程安全的ConcurrentQueue<T>队列

    队列(Queue)代表了一个先进先出的对象集合.当您需要对各项进行先进先出的访问时,则使用队列.当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队. ConcurrentQueue< ...

  6. [一起读源码]走进C#并发队列ConcurrentQueue的内部世界

    决定从这篇文章开始,开一个读源码系列,不限制平台语言或工具,任何自己感兴趣的都会写.前几天碰到一个小问题又读了一遍ConcurrentQueue的源码,那就拿C#中比较常用的并发队列Concurren ...

  7. 线程池 队列 synchronized

    线程池 BlockingQueue synchronized volatile 本章从线程池到阻塞队列BlockingQueue.从BlockingQueue到synchronized 和 volat ...

  8. 生产消费模式:多线程读写队列ConcurrentQueue

    需求:现需要将多个数据源的数据导入到目标数据库,这是一个经典的生产消费应用的例子. 直接上代码,看下实现: // 初始化列队缓冲区 队列大小为100 IDataCollection<List&l ...

  9. Linux多线程系列-2-条件变量的使用(线程安全队列的实现)

    多线程情况下,往往需要使用互斥变量来实现线程间的同步,实现资源正确共享. linux下使用如下变量和函数 //条件变量 pthread_cond_t int pthread_cond_init (pt ...

随机推荐

  1. VCS之Git

    Git -- open source distributed version control system -- A stream of snapshots(if no change,just lin ...

  2. 20 个超酷的 HTML5/CSS3 应用及源码

    [导读] 1.HTML5视频破碎重组特效,强大视觉冲击HTML5视频播放器很多,但是HTML5视频特效还是很少见的,这款HTML5视频破碎重组特效非常刺激,给人强大的视觉冲击.点击视频任意地方,HTM ...

  3. eCryptfs文件系统测试

    650) this.width=650;" onclick='window.open("http://blog.51cto.com/viewpic.php?refimg=" ...

  4. T-SQL运算符

    运算符 1.算术运算符 算术运算符 说明 + 加法 - 减法 * 乘法 / 除法 % 取模,两个整数相除后的余数 2.位运算符 位运算符 说明 &(与.and) 按位逻辑与运算 |(或.OR) ...

  5. cocos2d-x 3.2 DrawNode 绘图API

    关于Cocos2d-x 3.x 版本的绘图方法有两种: 1.使用DrawNode类绘制自定义图形. 2.继承Layer类重写draw()方法. 以上两种方法都可以绘制自定义图形,根据自己的需要选择合适 ...

  6. DNS原理及其解析过程(转)

    转自(http://369369.blog.51cto.com/319630/812889) 网络通讯大部分是基于TCP/IP的,而TCP/IP是基于IP地址的,所以计算机在网络上进行通讯时只能识别如 ...

  7. Bluetooth in Android 4.2 and 4.3(一):综述

    从Android 4.2开始,Bluetooth stack发生了重大改变:从Bluez换成了由Google和Broadcom联合开发的Bluedroid(当然,核心的部分还是Broadcom的,Go ...

  8. My集合框架第六弹 左式堆

    左式堆(Leftist Heaps)又称作最左堆.左倾堆.左式堆作为堆的一种,保留了堆的一些属性. 第1,左式堆仍然以二叉树的形式构建: 第2,左式堆的任意结点的值比其子树任意结点值均小(最小堆的特性 ...

  9. .NET/C#- EPPLUS DEMO

    强大的导出EXCEL,比NPOI更好用,更强大,可惜只有4.0版本的. 记录一下DEMO var sheet = p.Workbook.Worksheets.Add("My Sheet&qu ...

  10. C# try catch finally 执行

    try { //dosomething eg: int a = 1; int b = 2; int c = a + b; if(c>2) { return; } } catch(Exceptio ...