///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Runtime.InteropServices;
namespace JetBrains.Omea.Base
{
///
/// A pool which returns pinned GC handles for strings and keeps a limited number
/// of strings pinned.
///
public class PinnedStringPool: IDisposable
{
private int _size;
private GCHandle[] _gcHandles;
private int _freeIndex;
private bool _reusing;
///
/// Initializes the pool.
///
///
/// The maximum number of strings which can be held in the pool at the same time.
///
public PinnedStringPool( int size )
{
_size = size;
_gcHandles = new GCHandle[ size ];
}
///
/// Converts the data of the specified string to a pinned null-terminated character
/// array.
///
/// String which should be pinned
/// Address of the pinned character array
public IntPtr PinString( string str )
{
if ( _reusing )
{
_gcHandles [_freeIndex].Free();
}
char[] strChars = new char [str.Length+1];
str.CopyTo( 0, strChars, 0, str.Length );
strChars [str.Length] = '\0';
_gcHandles [_freeIndex] = GCHandle.Alloc( strChars, GCHandleType.Pinned );
IntPtr result = _gcHandles [_freeIndex].AddrOfPinnedObject();
_freeIndex++;
if ( _freeIndex == _gcHandles.Length )
{
_freeIndex = 0;
_reusing = true;
}
return result;
}
///
/// Unpins all handles and clears the array.
///
public void Dispose()
{
// if _reusing is set, all handles have been used at least once
int lastIndex = _reusing ? _size : _freeIndex;
for( int i=0; i