Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1751653
  • 博文数量: 100
  • 博客积分: 10122
  • 博客等级: 上将
  • 技术积分: 4092
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-04 20:28
文章分类

全部博文(100)

文章存档

2010年(2)

2009年(28)

2008年(70)

我的朋友

分类:

2008-10-24 06:29:58

The following problem is a realistic problem recently our project encounters. We now had a solution but imperfectly with limitation, so I put here to anticipate some better ideas.

==============================================
Problem description:
* Goal: A FIFO buffer for one reader and multiple concurrent writers

* Implementation Constraints
1. [VERY IMPORTANT]The code cannot be blocked, which means you cannot use Semaphore Wait or Mutex Wait, etc.
2. The following atomic operations are available to use:
oldValue = AtomicWrite(var, value), AW for short
oldValue = AtomicRead(var), AR for short
oldValue = AtomicIncrementDelta(var, delta), AID for short
oldValue = AtomicDecrementDelta(var, delta), ADD for short
oldValue = AtomicIncrement(var), the same as AtomicIncrementDelta(var, 1), AI for short
oldValue = AtomicDecrement(var), the same as AtomicDecrementDelta(var, 1), AD for short
3. The buffer should follow the FIFO scheme
4. Writes are running concurrently, they can call the following APIs in any unpredictable sequences.
5. There's only one reader.

* Required APIs
Store: Store a chunk of data into buffer
IsEmpty: Check if the buffer is empty
Get: Get a chunk of data into buffer, following the FIFO scheme.

===================================================================

The current solution:
* Constants
S: Number of buffer slots, which is equal to 2^n(n is integer)

* Variables
H: Head index number of the buffer
T: Tail index number of the buffer
N: Number of slots that has data
struct {
  f: Flag indicates if the buffer has data
  d: data
} B[S]: Buffer slots
F: Buffer state, {Normal, Abnormal}

* Initialization
H = 0
T = 0
N = 0
for i in (0..S): B[i].f = 0
F = Normal

* APIs Algorithm
function Store(data){
  while(F = Normal) {
    // Increment the tail
    oT = AI(T);

    // check if the slot is empty
    oF = AI(B[oT % S].f);

    if (oF >= 1) {
      // the slot is full(except when buffer is full, see *limitations*)
      AD(B[oT % S].f);
      // [!] Check if buffer is full
      if (AR(N) >= S) {
        // [!] Buffer now is screwed, any further operations on this buffer will fail
        F = Abnormal;
      }
      continue;
    } else {
      // the slot is empty(except when buffer is full, see *limitations*)
      // Set data before increase N
      B[oT % S].d = data;
      // Increase N, which means there's one more data now
      oN = AI(N);
      // Check if we're already reach the buffer limit, see *limitation*
      if(oN >= S){
        // [!] Buffer now is screwed, any further operations on this buffer will fail
        F = Abnormal;
      }
      break;
    }
  }

  return F == Normal?success: failed;
}

function IsEmpty(){
  return failed if F == Abnormal;

  return AR(N) > 0;
}

function Get(&data){
  return failed if F == Abnormal;

  if(AR(N)) {
    // Get data from head
    data = B[H % S]. d;
    // First Release the slot
    AD(B[H % S].f);
    // then Decrease N, which means there's one more slot empty now
    AD(N);
    // Increase the head
    ++H;
    return success;
  } else {
    return failed;
  }
}

* limitations
When the buffer is full, the buffer state is set to abnormal, further operations will all fail.
Although this limitation may not be a problem since buffer full normally means something wrong already happened.
阅读(1404) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-02-20 21:07:37

你的文章非常好,过来顶一下

chinaunix网友2009-02-20 21:07:37

你的文章非常好,过来顶一下

BenBear2008-10-24 09:36:24

没有 AtomicCompareExchange 这样的操作吗?

BenBear2008-10-24 09:36:24

没有 AtomicCompareExchange 这样的操作吗?