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. WS之cxf与spring整合1

    1.在web.xml中加入CXFServlet: <!-- 下面表示所有来自/cxfservice/*的请求,都交给 CXFServlet来处理 .--> <servlet>  ...

  2. Strider 持续集成(gitlab)

    Strider安装后运行: Mac: strider Ubuntu: bin/strider 本地运行时浏览器访问: http://127.0.0.1:3000 其他服务器:服务器地址 + 端口号(3 ...

  3. 苹果官网 demo The Elements 阅读随笔

    The Elements https://developer.apple.com/library/ios/samplecode/TheElements/Introduction/Intro.html# ...

  4. Openstack之Swift架构(Cloud Storage)

    Swift是OpenStack的子项目之一,也称为对象储存,适用于储存永久类型的静态数据,例如:虚拟机镜像文件.图片.存档备份等 复制的三个副本如何联系在一起? 让我们用一些具体场景和介绍一些组件,来 ...

  5. 用c++库函数轻松解决回文问题

    在<Accelerated C++>6.1学到的,这个解决回文问题的方案很简单,有必要把它记录下来. begin返回一个迭代器,它会从容器的最后一个元素开始,并且从后向前地逆序访问容器.e ...

  6. Maven+Spring Batch+Apache Commons VF学习

    Apache Commons VFS资料:例子:http://www.zihou.me/html/2011/04/12/3377.html详细例子:http://p7engqingyang.iteye ...

  7. JS鼠标滑轮事件的写法和按键的事件

    在body注册一下滑轮事件 <body onload="win_onload();"></body> 然后JS代码如下: function win_onlo ...

  8. How Tomcat Works(十四)

    我们已经知道,在tomcat中有四种类型的servlet容器,分别为Engine.Host.Context 和Wrapper,本文接下来对tomcat中Wrapper接口的标准实现进行说明. 对于每个 ...

  9. hdu 1171 Big Event in HDU(多重背包+二进制优化)

    题目链接:hdu1171 思路:将多重背包转为成完全背包和01背包问题,转化为01背包是用二进制思想,即件数amount用分解成若干个件数的集合,这里面数字可以组合成任意小于等于amount的件数 比 ...

  10. Compactness问题

    今天偶然在论坛讨论在halcon下紧密度的问题,现在总结一下 Calculation: If L is the length of the contour (see contlength) and F ...