public unsafe void Write(
UvStreamHandle handle,
MemoryPoolIterator2 start,
MemoryPoolIterator2 end,
int nBuffers,
Action <UvWriteReq, int, Exception, object> callback,
object state)
{
try
{
// add GCHandle to keeps this SafeHandle alive while request processing
_pins.Add(GCHandle.Alloc(this, GCHandleType.Normal));
var pBuffers = (Libuv.uv_buf_t *)_bufs;
if (nBuffers > BUFFER_COUNT)
{
// create and pin buffer array when it's larger than the pre-allocated one
var bufArray = new Libuv.uv_buf_t[nBuffers];
var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
_pins.Add(gcHandle);
pBuffers = (Libuv.uv_buf_t *)gcHandle.AddrOfPinnedObject();
}
var block = start.Block;
for (var index = 0; index < nBuffers; index++)
{
var blockStart = block == start.Block ? start.Index : block.Data.Offset;
var blockEnd = block == end.Block ? end.Index : block.Data.Offset + block.Data.Count;
// create and pin each segment being written
pBuffers[index] = Libuv.buf_init(
block.Pin() + blockStart,
blockEnd - blockStart);
block = block.Next;
}
_callback = callback;
_state = state;
_uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
}
catch
{
_callback = null;
_state = null;
Unpin(this);
var block = start.Block;
for (var index = 0; index < nBuffers; index++)
{
block.Unpin();
block = block.Next;
}
throw;
}
}