Keeping pointers to ExHeap arrays on the GC Heap

Apr 9, 2008 at 6:14 AM
I would like to be able to read a variable number of sectors off a disk and store the pointers to them in a heap allocated data structure such as ArrayList. There doesn't seem to be something like TRef<>, TContainer<> or ExRef<> that can hold an array. The code to create and insert a TContainer<> seemed to work, but the code to remove it didn't.

To insert (which compiled):

ArrayList! data = new ArrayList();
data.Add( new TContainer<byte[]! in ExHeap>( rdBuff ) );

but I try to remove like this and it won't compile:

byte[]! in ExHeap rdBuff = ((TContainer<byte[]! in ExHeap>)data0).Acquire();

The error says that byte* must be convertable to ITracked for use in TContainer<>.

Is there a good way to do what I want?
Coordinator
Apr 9, 2008 at 11:11 PM
Edited Apr 9, 2008 at 11:15 PM
A great example of something similar to what you're trying to do is PacketFifo, located here:

base\Contracts\Io.Net.Contracts\PacketFifo.sg

This is an ITracked class that wraps an array. This allows code such as this code to create and manipulate ExRef<PacketFifo> instances:

base\Services\NetStack\Channels.Nic\Nic.sg:

private ExRef<PacketFifo>! rxToDeviceFifo;
/.../
this.rxToDeviceFifo =
new ExRef<PacketFifo>(
new [ExHeap] PacketFifo(rxFifoSize),
false
);

Likewise, you will need to wrap your arrays in an ITracked struct before you can put ExRefs around them, as in this sample code:

struct ByteArrayTracked : ITracked
{
private byte[]! in ExHeap array;

public ByteArrayTracked([Claims] byte[]! in ExHeap array)
{
this.array = array;
}

public byte this[int i] {
get { expose(this) { return array[i]; } }
set { expose(this) { array[i] = value; } }
}

public int Length { get { expose(this) { return array.Length; } } }

void ITracked.Expose() {}
void ITracked.UnExpose() {}
void ITracked.Acquire() {}
void ITracked.Release() {}
void ITracked.Dispose() { delete array; }
}

/.../

byte[] in ExHeap array1 = new [ExHeap] byte[1000];
byte[] in ExHeap array2 = new [ExHeap] byte[1000];

ArrayList! data = new ArrayList();
data.Add(new ExRef<ByteArrayTracked>(new [ExHeap] ByteArrayTracked(array1), false/*synchronized*/));
data.Add(new ExRef<ByteArrayTracked>(new [ExHeap] ByteArrayTracked(array2), false/*synchronized*/));

ByteArrayTracked*! in ExHeap newBuffer1 = ((ExRef<ByteArrayTracked>!)data[0]).Acquire();
(*newBuffer1)[0] = 123;
delete newBuffer1;

I've verified that this builds. Let me know if this serves your purposes, and I hope this helps.
--
Derrick Coetzee
Microsoft Research Operating Systems Group developer
Apr 10, 2008 at 5:11 AM
Edited Apr 10, 2008 at 5:11 AM
That's exactly what I was looking for, thanks!

It also seems quite verbose, confusing and messy...