/*
* PowerOfTwoAllocator.java
* JCollider
*
* Copyright (c) 2004-2010 Hanns Holger Rutz. All rights reserved.
*
* This software is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either
* version 2, june 1991 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License (gpl.txt) along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* For further information, please contact Hanns Holger Rutz at
* contact@sciss.de , or visit http://www.sciss.de/jcollider
*
*
* JCollider is closely modelled after SuperCollider Language,
* often exhibiting a direct translation from Smalltalk to Java.
* SCLang is a software originally developed by James McCartney,
* which has become an Open Source project.
* See http://www.audiosynth.com/ for details.
*
*
* Changelog:
* 04-Aug-05 created
* 24-Jul-06 implements BlockAllocator
*/
package de.sciss.jcollider;
import java.util.ArrayList;
import java.util.List;
/**
* Quite a 1:1 translation from SClang, this
* is used as the default bus allocator by the server.
*
* @todo unlike the node allocator, this cannot
* handle different client IDs. have to find
* out how different clients can peacefully
* coexist on the same server.
*
* @author Hanns Holger Rutz
* @version 0.32, 25-Feb-08
*/
public class PowerOfTwoAllocator
implements BlockAllocator
{
private final int size;
private int pos;
private final Block[] allocatedBlocks;
private final Block[] freeBlocks;
public PowerOfTwoAllocator( int size )
{
this( size, 0 );
}
public PowerOfTwoAllocator( int size, int pos )
{
this.size = size;
this.pos = pos;
allocatedBlocks = new Block[ size ];
freeBlocks = new Block[ 32 ];
}
public int alloc( final int n )
{
final int result;
int np2, sizeClass;
Block node;
for( np2 = 1, sizeClass = 0; np2 < n; np2 <<= 1, sizeClass++ ) ; // next power of two
node = freeBlocks[ sizeClass ];
if( node != null ) {
freeBlocks[ sizeClass ] = node.next;
result = node.address;
} else if( pos + np2 <= size ) {
allocatedBlocks[ pos ] = new Block( pos, np2, sizeClass );
result = pos;
pos += np2;
} else {
result = -1;
}
return result;
}
public void free( int address )
{
final Block node = allocatedBlocks[ address ];
if( node != null ) {
node.next = freeBlocks[ node.sizeClass ];
freeBlocks[ node.sizeClass ] = node;
}
}
public List getAllocatedBlocks()
{
final List result = new ArrayList();
for( int i = 0; i < allocatedBlocks.length; i++ ) {
if( allocatedBlocks[ i ] != null ) result.add( allocatedBlocks[ i ]);
}
return result;
}
public static class Factory
implements BlockAllocator.Factory
{
public BlockAllocator create( int size )
{
return new PowerOfTwoAllocator( size );
}
public BlockAllocator create( int size, int pos )
{
return new PowerOfTwoAllocator( size, pos );
}
}
private static class Block
implements BlockAllocator.Block
{
protected final int address;
private final int size;
protected final int sizeClass;
protected Block next = null;
protected Block( int address, int size, int sizeClass )
{
this.address = address;
this.size = size;
this.sizeClass = sizeClass;
}
public int getAddress()
{
return address;
}
public int getSize()
{
return size;
}
}
}