root/trunk/thune/list.c

Revision 458, 4.6 kB (checked in by krobillard, 15 months ago)

Merged Thune thread_safe branch into trunk (r386:457)

Line 
1/*============================================================================
2    Urlan Interpreter
3    Copyright (C) 2005-2007  Karl Robillard
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18===========================================================================*/
19
20
21#include "urlan.h"
22#include "list.h"
23
24
25UIndex ur_makeList( UThread* ut, int len, UBlock** blkPtr )
26{
27    UIndex blkN;
28    UBlock* blk;
29    UCell* it;
30    UCell* end;
31    //UCell* next;
32
33    len = len * 2 + 2;
34
35    blkN = ur_makeBlock( len );
36    blk = ur_blockPtr( blkN );
37    blk->used = 2;
38
39    it  = blk->ptr.cells;
40    end = it + len;
41
42    ur_initType( it, UT_UNSET );
43    it->list.prev = -1;
44    it->list.next = LIST_TAIL;
45    it->list.free = 0;
46    //it->list.free = (len == 2) ? 0 : 2;
47    ++it;
48
49    ur_initType( it, UT_UNSET );
50    it->list.prev = LIST_HEAD;
51    it->list.next = 0;
52    it->list.free = -1;
53#if 0
54    ++it;
55
56    // Disabled initialization of free list because the free nodes cannot
57    // be used until they fall within blk->used range.
58
59    while( it != end )
60    {
61        next = it + 2;
62
63        ur_initType( it, UT_UNSET );
64        it->list.prev = -1;
65        it->list.next = -1;
66        it->list.free = (next == end) ? 0 : next - blk->ptr.cells;
67
68        it = next;
69    }
70#endif
71
72    if( blkPtr )
73        *blkPtr = blk;
74
75    return blkN;
76}
77
78
79void ur_listInsertValue( UBlock* blk, UIndex nodeIndex, UCell* newVal )
80{
81    UIndex nodeN;
82    UCell* node;
83    UCell* prev;
84    UCell* it = blk->ptr.cells;
85
86    nodeN = it->list.free;
87    if( nodeN )
88    {
89        it->list.free = it[ nodeN ].list.free;
90    }
91    else
92    {
93        ur_arrayReserve( blk, sizeof(UCell), blk->used + 2 );
94        nodeN = blk->used;
95        blk->used += 2;
96        it = blk->ptr.cells;
97    }
98
99    it += nodeIndex;
100
101    prev = blk->ptr.cells + it->list.prev;
102    prev->list.next = nodeN;
103    it->list.prev = nodeN;
104
105    node = blk->ptr.cells + nodeN;
106    ur_initType( node, UT_UNSET );
107    node->list.linked = 1;
108    node->list.prev   = prev - blk->ptr.cells;
109    node->list.next   = it - blk->ptr.cells;
110    node->list.free   = -1;
111
112    ++node;
113    ur_copyCell( node, *newVal );
114}
115
116
117/*
118   Returns next series.it or -1 if node is not linked to the list.
119*/
120UIndex ur_listRemove( UBlock* blk, UIndex nodeIndex )
121{
122    UIndex nextI;
123    UCell* it;
124    UCell* cells = blk->ptr.cells;
125    UCell* node = cells + nodeIndex;
126
127    if( ! node->list.linked )       // Includes head & tail.
128        return -1;
129
130    nextI = node->list.next;
131
132    it = cells + node->list.prev;
133    it->list.next = node->list.next;
134
135    it = cells + node->list.next;
136    it->list.prev = node->list.prev;
137
138    node->list.linked = 0;
139    node->list.prev   = -1;
140    node->list.next   = -1;
141    node->list.free   = cells->list.free;
142
143    cells->list.free = nodeIndex;
144
145    /*
146    ++node;
147    ur_initType( node, UT_UNSET );
148    */
149
150    // NOTE: If this is the last node in the block we can
151    // optimize GC by moving blk->used down until a used node
152    // is found.
153
154    return nextI;
155}
156
157
158/*
159   Returns previous series.it or -1 if node is not linked to the list.
160*/
161UIndex ur_listClear( UBlock* blk, UIndex nodeIndex )
162{
163    UCell* it;
164
165    if( nodeIndex == LIST_TAIL )
166        return LIST_TAIL;
167
168    it = blk->ptr.cells + nodeIndex;
169    if( it->list.linked )
170    {
171        UIndex next;
172        UIndex prevI = it->list.prev;
173        UCell* cells = blk->ptr.cells;
174
175        cells[ prevI ].list.next = LIST_TAIL;
176        cells[ LIST_TAIL ].list.prev = prevI;
177
178        do
179        {
180            next = it->list.next;
181
182            it->list.linked = 0;
183            it->list.prev   = -1;
184            it->list.next   = -1;
185            it->list.free   = (next == LIST_TAIL) ? cells->list.free : next;
186
187            /*
188            ++it;
189            ur_initType( it, UT_UNSET );
190            */
191
192            it = cells + next;
193        }
194        while( it->list.next > 0 );
195
196        cells->list.free = nodeIndex;
197
198        return LIST_TAIL;
199    }
200    return -1;
201}
202
203
204/*EOF*/
Note: See TracBrowser for help on using the browser.