File: ContiguousBlockAllocator.schelp

package info (click to toggle)
supercollider 1%3A3.13.0%2Brepack-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 80,292 kB
  • sloc: cpp: 476,363; lisp: 84,680; ansic: 77,685; sh: 25,509; python: 7,909; makefile: 3,440; perl: 1,964; javascript: 974; xml: 826; java: 677; yacc: 314; lex: 175; objc: 152; ruby: 136
file content (84 lines) | stat: -rw-r--r-- 3,754 bytes parent folder | download | duplicates (2)
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
84
class:: ContiguousBlockAllocator
summary:: for better handling of dynamic allocation
related:: Classes/Server, Classes/PowerOfTwoAllocator, Guides/MultiClient_Setups
categories:: Control

description::

The default allocator used in servers to allocate bus numbers and buffer numbers. Compared to its predecessor, link::Classes/PowerOfTwoAllocator::, it can reserve a block of numbers at the beginning of its range, and it can offset its entire range of numbers to support multiple clientIDs.

ClassMethods::

method::new
Create a new allocator with emphasis::size:: slots. You may block off the first emphasis::pos:: slots (the server's audioBusAllocator does this to reserve the hardware input and output buses).

InstanceMethods::

private::prReserve, prSplit, addToFreed, blocks, findNext, findPrevious, prFindNext, prFindPrevious, removeFromFreed

subsection:: Public interface

method::alloc
Return the starting index of a free block that is emphasis::n:: slots wide. The default is 1 slot.

Note that the returned address is not guaranteed to be the lowest possible address that can satisfy the requested size. It should be adjacent to a previously allocated block, however (to minimize fragmentation of the address space).

method::free
Free a previously allocated block starting at emphasis::address::.

method::reserve
Mark a specific range of addresses as used so that the alloc method will not return any addresses within that range. 

method::findAvailable
Given an integer width of a desired block, find and return a code::ContiguousBlock:: object whose code::start:: is the beginning address of the block and whose code::size:: is the width. This method only queries the allocator; it does not change the state. If you obtain an address using code::findAvailable::, there is no guarantee that a later call will not return the same address. So, in general, use link::#-alloc:: to request an address. (code::alloc:: calls code::findAvailable:: and then code::reserve::.)

This method could be considered "half-private": It may be useful for queries, but in general, you can get everything you need from link::#-alloc::, link::#-free:: and link::#-reserve::.

subsection:: Status and debugging

You may query these state variables, but it is not recommended to change them outside of the public interface.

method::debug
	Post internal state of allocator for debugging.

method::size
	The number of id numbers it can allocate.

method::pos
	The allocator's offset for a reserved block (e.g. for hardware input and output buses).

method::addrOffset
	The offset of the allocator's address range, which is used to accomodate multiple clientIDs.

method::top
	The address of the last empty block.

EXAMPLES::

code::
c = ContiguousBlockAllocator(10);
c.alloc(5);  // 0 = first available
c.alloc(2);  // 5
c.alloc(4);  // nil -- no block of 4 available

c.free(1);  // no-op: nothing at 1 to free

c.free(0);

c.alloc(3);  // 0: tries to reuse previously-freed space first

c.alloc(3);  // 7


// Adjacency
c = ContiguousBlockAllocator(24);

// reserve every 4th
(0, 4 .. 23).do { |i| c.reserve(i) };

10.do { c.findAvailable(1).postln };
::

In the last line of the second example, code::findAvailable:: may locate any of indices 1, 5, 9, 13, or 17. (21 would not be used until a suitable block could not be found in the other empty spaces.) If you were to allocate a single address, then the empty block of three would always be reduced to an empty block of two (instead of dividing the empty space in half and having two empty single-address blocks).

It may be surprising that the algorithm does not favor lower-index blocks, but if two addresses A and B have been previously used and freed, there is no inherent reason to prefer A if A < B.