ArrayBuilderQueue

It basically works like a combination of the StringBuilder and Queue objects. You enqueue arrays of T, and you dequeue custom sized chunks of the array. What makes it nice is that I’ve optimized memory usage so it never creates any temp arrays internally except the one returned to you when you eat (of course).

Added some comments in case you need to change anything.

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

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

/// <summary>

/// Works like a Queue object except it enqueues arrays and lets you dequeue custom sized chunks of the arrays enqueued

/// </summary>

/// <typeparam name="T">Array type</typeparam>

publicclassArrayBuilderQueue<T>

{

privateList<Array>buffer=newList<Array>();

privateintcurrentArrayPos=0;

publicintLength{get;privateset;}

/// <summary>

/// Adds an array to the queue

/// </summary>

/// <param name="items">Array of items to add</param>

publicvoidEnqueue(T[]items)

{

lock(buffer)

{

if(items==null)

return;

buffer.Add(items);

Length+=items.Length;

}

}

publicvoidClear()

{

lock(buffer)

{

buffer.Clear();

Length=0;

currentArrayPos=0;

}

}

/// <summary>

/// Dequeues items from buffer.

/// </summary>

/// <param name="count">Number of items</param>

/// <returns>Array of items</returns>

publicT[]Dequeue(intcount)

{

lock(buffer)

{

count=Math.Min(count,Length);

T[]ret=newT[count];

inteaten=0;

intretPos=0;

while(eaten<count)

{

// Check how much remains of first array

intbl=0;

if(buffer.Count>0)

bl=buffer[0].Length;

intremaining=bl-currentArrayPos;

// Nothing?

while(remaining==0&&buffer.Count>0)

{

// Remove it and recalculate

buffer.RemoveAt(0);

currentArrayPos=0;

if(buffer.Count>0)

{

// Still got some, try next

if(buffer[0]!=null)

remaining=buffer[0].Length-currentArrayPos;

}

}

// Copy data to return var

inteatSize=Math.Min(remaining,count-eaten);

if(eatSize>0)

Array.Copy(buffer[0],currentArrayPos,ret,retPos,eatSize);

// Update internal tracking

retPos+=eatSize;// Where we are in buffer we are copying to

currentArrayPos+=eatSize;// Where we are in current array after eating