博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c# 高效的线程安全队列ConcurrentQueue(下) Segment类
阅读量:4311 次
发布时间:2019-06-06

本文共 2757 字,大约阅读时间需要 9 分钟。

 

 

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;
}

转载于:https://www.cnblogs.com/lvdongjie/p/5428357.html

你可能感兴趣的文章
C++——string类和标准模板库
查看>>
zt C++ list 类学习笔记
查看>>
git常用命令
查看>>
探讨和比较Java和_NET的序列化_Serialization_框架
查看>>
1、jQuery概述
查看>>
数组比较大小的几种方法及math是方法
查看>>
FTP站点建立 普通电脑版&&服务器版
查看>>
js 给一段代码,给出运行后的最终结果的一些综合情况、
查看>>
webservice 详解
查看>>
js自动补全实例
查看>>
VS无法启动调试:“生成下面的模块时,启用了优化或没有调试信息“
查看>>
npm 安装 sass=-=-=
查看>>
WINFORM中加入WPF控件并绑定数据源实现跨线程自动更新
查看>>
C#类对象的事件定义
查看>>
各类程序员学习路线图
查看>>
HDU 5510 Bazinga KMP
查看>>
关于select @@IDENTITY的初识
查看>>
ASP.NET MVC ajax提交 防止CSRF攻击
查看>>
关于CSS伪类选择器
查看>>
适用于带文字 和图片的垂直居中方法
查看>>