diff options
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/abq.c | 199 | ||||
| -rw-r--r-- | mps/code/abq.h | 33 | ||||
| -rw-r--r-- | mps/code/abqtest.c | 57 |
3 files changed, 169 insertions, 120 deletions
diff --git a/mps/code/abq.c b/mps/code/abq.c index e29a9786599..c327a721a54 100644 --- a/mps/code/abq.c +++ b/mps/code/abq.c | |||
| @@ -1,18 +1,15 @@ | |||
| 1 | /* abq.c: AVAILABLE BLOCK QUEUE | 1 | /* abq.c: QUEUE IMPLEMENTATION |
| 2 | * | 2 | * |
| 3 | * $Id$ | 3 | * $Id$ |
| 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. |
| 5 | * | 5 | * |
| 6 | * .readership: Any MPS developer | 6 | * .purpose: A fixed-length FIFO queue. |
| 7 | * | 7 | * |
| 8 | * .purpose: A FIFO queue substrate for <code/poolmv2.c> | 8 | * .design: <design/abq/> |
| 9 | * | ||
| 10 | * .design: See <design/poolmvt/> | ||
| 11 | */ | 9 | */ |
| 12 | 10 | ||
| 13 | #include "meter.h" | 11 | #include "meter.h" |
| 14 | #include "abq.h" | 12 | #include "abq.h" |
| 15 | #include "cbs.h" | ||
| 16 | #include "mpm.h" | 13 | #include "mpm.h" |
| 17 | 14 | ||
| 18 | SRCID(abq, "$Id$"); | 15 | SRCID(abq, "$Id$"); |
| @@ -20,37 +17,39 @@ SRCID(abq, "$Id$"); | |||
| 20 | 17 | ||
| 21 | /* Private prototypes */ | 18 | /* Private prototypes */ |
| 22 | 19 | ||
| 23 | static Size ABQQueueSize(Count elements); | 20 | static Size ABQQueueSize(Count elements, Size elementSize); |
| 24 | static Index ABQNextIndex(ABQ abq, Index index); | 21 | static Index ABQNextIndex(ABQ abq, Index index); |
| 22 | static Addr ABQElement(ABQ abq, Index index); | ||
| 25 | 23 | ||
| 26 | 24 | ||
| 27 | /* Methods */ | 25 | /* Methods */ |
| 28 | 26 | ||
| 29 | /* ABQInit -- Initialize an ABQ | 27 | /* ABQInit -- Initialize an ABQ |
| 30 | * | 28 | * |
| 31 | * items is the number of items the queue can hold | 29 | * elements is the number of elements the queue can hold |
| 32 | */ | 30 | */ |
| 33 | Res ABQInit(Arena arena, ABQ abq, void *owner, Count items) | 31 | Res ABQInit(Arena arena, ABQ abq, void *owner, Count elements, Size elementSize) |
| 34 | { | 32 | { |
| 35 | Count elements; | ||
| 36 | void *p; | 33 | void *p; |
| 37 | Res res; | 34 | Res res; |
| 38 | 35 | ||
| 39 | AVERT(Arena, arena); | 36 | AVERT(Arena, arena); |
| 40 | AVER(abq != NULL); | 37 | AVER(abq != NULL); |
| 41 | AVER(items > 0); | 38 | AVER(elements > 0); |
| 42 | 39 | ||
| 43 | elements = items + 1; | 40 | /* Necessary in order to be able to distinguish "empty" from "full" */ |
| 44 | 41 | elements = elements + 1; | |
| 45 | res = ControlAlloc(&p, arena, ABQQueueSize(elements), | 42 | |
| 43 | res = ControlAlloc(&p, arena, ABQQueueSize(elements, elementSize), | ||
| 46 | /* withReservoirPermit */ FALSE); | 44 | /* withReservoirPermit */ FALSE); |
| 47 | if (res != ResOK) | 45 | if (res != ResOK) |
| 48 | return res; | 46 | return res; |
| 49 | 47 | ||
| 50 | abq->elements = elements; | 48 | abq->elements = elements; |
| 49 | abq->elementSize = elementSize; | ||
| 51 | abq->in = 0; | 50 | abq->in = 0; |
| 52 | abq->out = 0; | 51 | abq->out = 0; |
| 53 | abq->queue = (CBSBlock *)p; | 52 | abq->queue = p; |
| 54 | 53 | ||
| 55 | METER_INIT(abq->push, "push", owner); | 54 | METER_INIT(abq->push, "push", owner); |
| 56 | METER_INIT(abq->pop, "pop", owner); | 55 | METER_INIT(abq->pop, "pop", owner); |
| @@ -67,19 +66,12 @@ Res ABQInit(Arena arena, ABQ abq, void *owner, Count items) | |||
| 67 | /* ABQCheck -- validate an ABQ */ | 66 | /* ABQCheck -- validate an ABQ */ |
| 68 | Bool ABQCheck(ABQ abq) | 67 | Bool ABQCheck(ABQ abq) |
| 69 | { | 68 | { |
| 70 | Index index; | ||
| 71 | |||
| 72 | CHECKS(ABQ, abq); | 69 | CHECKS(ABQ, abq); |
| 73 | CHECKL(abq->elements > 0); | 70 | CHECKL(abq->elements > 0); |
| 71 | CHECKL(abq->elementSize > 0); | ||
| 74 | CHECKL(abq->in < abq->elements); | 72 | CHECKL(abq->in < abq->elements); |
| 75 | CHECKL(abq->out < abq->elements); | 73 | CHECKL(abq->out < abq->elements); |
| 76 | CHECKL(abq->queue != NULL); | 74 | CHECKL(abq->queue != NULL); |
| 77 | /* Is this really a local check? */ | ||
| 78 | for (index = abq->out; index != abq->in; ) { | ||
| 79 | CHECKL(CBSBlockCheck(abq->queue[index])); | ||
| 80 | if (++index == abq->elements) | ||
| 81 | index = 0; | ||
| 82 | } | ||
| 83 | 75 | ||
| 84 | return TRUE; | 76 | return TRUE; |
| 85 | } | 77 | } |
| @@ -95,7 +87,7 @@ void ABQFinish(Arena arena, ABQ abq) | |||
| 95 | METER_EMIT(&abq->pop); | 87 | METER_EMIT(&abq->pop); |
| 96 | METER_EMIT(&abq->peek); | 88 | METER_EMIT(&abq->peek); |
| 97 | METER_EMIT(&abq->delete); | 89 | METER_EMIT(&abq->delete); |
| 98 | ControlFree(arena, abq->queue, ABQQueueSize(abq->elements)); | 90 | ControlFree(arena, abq->queue, ABQQueueSize(abq->elements, abq->elementSize)); |
| 99 | 91 | ||
| 100 | abq->elements = 0; | 92 | abq->elements = 0; |
| 101 | abq->queue = NULL; | 93 | abq->queue = NULL; |
| @@ -104,18 +96,17 @@ void ABQFinish(Arena arena, ABQ abq) | |||
| 104 | } | 96 | } |
| 105 | 97 | ||
| 106 | 98 | ||
| 107 | /* ABQPush -- push a block onto the tail of the ABQ */ | 99 | /* ABQPush -- push an element onto the tail of the ABQ */ |
| 108 | Res ABQPush(ABQ abq, CBSBlock block) | 100 | Res ABQPush(ABQ abq, Addr element) |
| 109 | { | 101 | { |
| 110 | AVERT(ABQ, abq); | 102 | AVERT(ABQ, abq); |
| 111 | AVERT(CBSBlock, block); | ||
| 112 | 103 | ||
| 113 | METER_ACC(abq->push, ABQDepth(abq)); | 104 | METER_ACC(abq->push, ABQDepth(abq)); |
| 114 | 105 | ||
| 115 | if (ABQIsFull(abq)) | 106 | if (ABQIsFull(abq)) |
| 116 | return ResFAIL; | 107 | return ResFAIL; |
| 117 | 108 | ||
| 118 | abq->queue[abq->in] = block; | 109 | mps_lib_memcpy(ABQElement(abq, abq->in), element, abq->elementSize); |
| 119 | abq->in = ABQNextIndex(abq, abq->in); | 110 | abq->in = ABQNextIndex(abq, abq->in); |
| 120 | 111 | ||
| 121 | AVERT(ABQ, abq); | 112 | AVERT(ABQ, abq); |
| @@ -123,10 +114,10 @@ Res ABQPush(ABQ abq, CBSBlock block) | |||
| 123 | } | 114 | } |
| 124 | 115 | ||
| 125 | 116 | ||
| 126 | /* ABQPop -- pop a block from the head of the ABQ */ | 117 | /* ABQPop -- pop an element from the head of the ABQ */ |
| 127 | Res ABQPop(ABQ abq, CBSBlock *blockReturn) | 118 | Res ABQPop(ABQ abq, Addr elementReturn) |
| 128 | { | 119 | { |
| 129 | AVER(blockReturn != NULL); | 120 | AVER(elementReturn != NULL); |
| 130 | AVERT(ABQ, abq); | 121 | AVERT(ABQ, abq); |
| 131 | 122 | ||
| 132 | METER_ACC(abq->pop, ABQDepth(abq)); | 123 | METER_ACC(abq->pop, ABQDepth(abq)); |
| @@ -134,8 +125,7 @@ Res ABQPop(ABQ abq, CBSBlock *blockReturn) | |||
| 134 | if (ABQIsEmpty(abq)) | 125 | if (ABQIsEmpty(abq)) |
| 135 | return ResFAIL; | 126 | return ResFAIL; |
| 136 | 127 | ||
| 137 | *blockReturn = abq->queue[abq->out]; | 128 | mps_lib_memcpy(elementReturn, ABQElement(abq, abq->out), abq->elementSize); |
| 138 | AVERT(CBSBlock, *blockReturn); | ||
| 139 | 129 | ||
| 140 | abq->out = ABQNextIndex(abq, abq->out); | 130 | abq->out = ABQNextIndex(abq, abq->out); |
| 141 | 131 | ||
| @@ -145,9 +135,9 @@ Res ABQPop(ABQ abq, CBSBlock *blockReturn) | |||
| 145 | 135 | ||
| 146 | 136 | ||
| 147 | /* ABQPeek -- peek at the head of the ABQ */ | 137 | /* ABQPeek -- peek at the head of the ABQ */ |
| 148 | Res ABQPeek(ABQ abq, CBSBlock *blockReturn) | 138 | Res ABQPeek(ABQ abq, Addr elementReturn) |
| 149 | { | 139 | { |
| 150 | AVER(blockReturn != NULL); | 140 | AVER(elementReturn != NULL); |
| 151 | AVERT(ABQ, abq); | 141 | AVERT(ABQ, abq); |
| 152 | 142 | ||
| 153 | METER_ACC(abq->peek, ABQDepth(abq)); | 143 | METER_ACC(abq->peek, ABQDepth(abq)); |
| @@ -155,8 +145,7 @@ Res ABQPeek(ABQ abq, CBSBlock *blockReturn) | |||
| 155 | if (ABQIsEmpty(abq)) | 145 | if (ABQIsEmpty(abq)) |
| 156 | return ResFAIL; | 146 | return ResFAIL; |
| 157 | 147 | ||
| 158 | *blockReturn = abq->queue[abq->out]; | 148 | mps_lib_memcpy(elementReturn, ABQElement(abq, abq->out), abq->elementSize); |
| 159 | AVERT(CBSBlock, *blockReturn); | ||
| 160 | 149 | ||
| 161 | /* Identical to pop, but don't increment out */ | 150 | /* Identical to pop, but don't increment out */ |
| 162 | 151 | ||
| @@ -165,46 +154,49 @@ Res ABQPeek(ABQ abq, CBSBlock *blockReturn) | |||
| 165 | } | 154 | } |
| 166 | 155 | ||
| 167 | 156 | ||
| 168 | /* ABQDelete -- delete a block from the ABQ */ | 157 | typedef struct ABQDeleteClosureStruct *ABQDeleteClosure; |
| 169 | Res ABQDelete(ABQ abq, CBSBlock block) | 158 | typedef struct ABQDeleteClosureStruct { |
| 159 | Addr element; | ||
| 160 | Size elementSize; | ||
| 161 | Res res; | ||
| 162 | } ABQDeleteClosureStruct; | ||
| 163 | |||
| 164 | |||
| 165 | static Res ABQDeleteCallback(ABQDisposition *dispositionReturn, Addr element, | ||
| 166 | void *closureP) | ||
| 167 | { | ||
| 168 | ABQDeleteClosure closure = closureP; | ||
| 169 | if (mps_lib_memcmp(element, closure->element, closure->elementSize) == 0) { | ||
| 170 | *dispositionReturn = ABQDispositionDELETE; | ||
| 171 | closure->res = ResOK; | ||
| 172 | } else { | ||
| 173 | *dispositionReturn = ABQDispositionKEEP; | ||
| 174 | } | ||
| 175 | return ResOK; | ||
| 176 | } | ||
| 177 | |||
| 178 | |||
| 179 | /* ABQDelete -- delete an element from the ABQ */ | ||
| 180 | Res ABQDelete(ABQ abq, Addr element) | ||
| 170 | { | 181 | { |
| 171 | Index index, next, in; | 182 | ABQDeleteClosureStruct closure; |
| 172 | CBSBlock *queue; | ||
| 173 | 183 | ||
| 174 | AVERT(ABQ, abq); | 184 | AVERT(ABQ, abq); |
| 175 | AVERT(CBSBlock, block); | ||
| 176 | 185 | ||
| 177 | METER_ACC(abq->delete, ABQDepth(abq)); | 186 | METER_ACC(abq->delete, ABQDepth(abq)); |
| 178 | 187 | ||
| 179 | index = abq->out; | 188 | closure.element = element; |
| 180 | in = abq->in; | 189 | closure.elementSize = abq->elementSize; |
| 181 | queue = abq->queue; | 190 | closure.res = ResFAIL; |
| 182 | |||
| 183 | while (index != in) { | ||
| 184 | if (queue[index] == block) { | ||
| 185 | goto found; | ||
| 186 | } | ||
| 187 | index = ABQNextIndex(abq, index); | ||
| 188 | } | ||
| 189 | |||
| 190 | return ResFAIL; | ||
| 191 | 191 | ||
| 192 | found: | 192 | ABQIterate(abq, ABQDeleteCallback, &closure); |
| 193 | /* index points to the node to be removed */ | 193 | |
| 194 | next = ABQNextIndex(abq, index); | 194 | return closure.res; |
| 195 | while (next != in) { | ||
| 196 | queue[index] = queue[next]; | ||
| 197 | index = next; | ||
| 198 | next = ABQNextIndex(abq, index); | ||
| 199 | } | ||
| 200 | abq->in = index; | ||
| 201 | AVERT(ABQ, abq); | ||
| 202 | return ResOK; | ||
| 203 | } | 195 | } |
| 204 | 196 | ||
| 205 | 197 | ||
| 206 | /* ABQDescribe -- Describe an ABQ */ | 198 | /* ABQDescribe -- Describe an ABQ */ |
| 207 | Res ABQDescribe(ABQ abq, mps_lib_FILE *stream) | 199 | Res ABQDescribe(ABQ abq, ABQDescribeElement describeElement, mps_lib_FILE *stream) |
| 208 | { | 200 | { |
| 209 | Res res; | 201 | Res res; |
| 210 | Index index; | 202 | Index index; |
| @@ -224,11 +216,10 @@ Res ABQDescribe(ABQ abq, mps_lib_FILE *stream) | |||
| 224 | return res; | 216 | return res; |
| 225 | 217 | ||
| 226 | for (index = abq->out; index != abq->in; ) { | 218 | for (index = abq->out; index != abq->in; ) { |
| 227 | res = CBSBlockDescribe(abq->queue[index], stream); | 219 | res = (*describeElement)(ABQElement(abq, index), stream); |
| 228 | if(res != ResOK) | 220 | if(res != ResOK) |
| 229 | return res; | 221 | return res; |
| 230 | if (++index == abq->elements) | 222 | index = ABQNextIndex(abq, index); |
| 231 | index = 0; | ||
| 232 | } | 223 | } |
| 233 | 224 | ||
| 234 | res = WriteF(stream, "\n", NULL); | 225 | res = WriteF(stream, "\n", NULL); |
| @@ -274,7 +265,7 @@ Bool ABQIsFull(ABQ abq) | |||
| 274 | } | 265 | } |
| 275 | 266 | ||
| 276 | 267 | ||
| 277 | /* ABQDepth -- return the number of items in an ABQ */ | 268 | /* ABQDepth -- return the number of elements in an ABQ */ |
| 278 | Count ABQDepth(ABQ abq) | 269 | Count ABQDepth(ABQ abq) |
| 279 | { | 270 | { |
| 280 | Index out, in; | 271 | Index out, in; |
| @@ -290,13 +281,65 @@ Count ABQDepth(ABQ abq) | |||
| 290 | } | 281 | } |
| 291 | 282 | ||
| 292 | 283 | ||
| 284 | /* ABQDispositionCheck -- check method for an ABQDisposition value */ | ||
| 285 | static Bool ABQDispositionCheck(ABQDisposition disposition) | ||
| 286 | { | ||
| 287 | CHECKL(disposition == ABQDispositionKEEP | ||
| 288 | || disposition == ABQDispositionDELETE); | ||
| 289 | UNUSED(disposition); /* <code/mpm.c#check.unused> */ | ||
| 290 | |||
| 291 | return TRUE; | ||
| 292 | } | ||
| 293 | |||
| 294 | |||
| 295 | /* ABQIterate -- call 'iterate' for each element in an ABQ */ | ||
| 296 | void ABQIterate(ABQ abq, ABQIterateMethod iterate, void *closureP) | ||
| 297 | { | ||
| 298 | Index copy, index, in; | ||
| 299 | Res res; | ||
| 300 | |||
| 301 | AVERT(ABQ, abq); | ||
| 302 | AVER(FUNCHECK(iterate)); | ||
| 303 | |||
| 304 | copy = abq->out; | ||
| 305 | index = abq->out; | ||
| 306 | in = abq->in; | ||
| 307 | |||
| 308 | while (index != in) { | ||
| 309 | Addr element = ABQElement(abq, index); | ||
| 310 | ABQDisposition disposition = ABQDispositionNONE; | ||
| 311 | res = (*iterate)(&disposition, element, closureP); | ||
| 312 | AVERT(ABQDisposition, disposition); | ||
| 313 | if (disposition == ABQDispositionKEEP) { | ||
| 314 | if (copy != index) | ||
| 315 | mps_lib_memcpy(ABQElement(abq, copy), element, abq->elementSize); | ||
| 316 | copy = ABQNextIndex(abq, copy); | ||
| 317 | } | ||
| 318 | index = ABQNextIndex(abq, index); | ||
| 319 | if (res != ResOK) | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | |||
| 323 | /* If any elements were deleted, need to copy remainder of queue. */ | ||
| 324 | if (copy != index) { | ||
| 325 | while (index != in) { | ||
| 326 | mps_lib_memcpy(ABQElement(abq, copy), ABQElement(abq, index), | ||
| 327 | abq->elementSize); | ||
| 328 | copy = ABQNextIndex(abq, copy); | ||
| 329 | index = ABQNextIndex(abq, index); | ||
| 330 | } | ||
| 331 | abq->in = copy; | ||
| 332 | } | ||
| 333 | |||
| 334 | AVERT(ABQ, abq); | ||
| 335 | } | ||
| 336 | |||
| 337 | |||
| 293 | /* ABQQueueSize -- calculate the storage required for the vector to | 338 | /* ABQQueueSize -- calculate the storage required for the vector to |
| 294 | store elements items */ | 339 | store the elements */ |
| 295 | static Size ABQQueueSize(Count elements) | 340 | static Size ABQQueueSize(Count elements, Size elementSize) |
| 296 | { | 341 | { |
| 297 | /* strange but true: the sizeof expression calculates the size of a | 342 | return (Size)(elements * elementSize); |
| 298 | single queue element */ | ||
| 299 | return (Size)(sizeof(((ABQ)NULL)->queue[0]) * elements); | ||
| 300 | } | 343 | } |
| 301 | 344 | ||
| 302 | 345 | ||
| @@ -310,6 +353,12 @@ static Index ABQNextIndex(ABQ abq, Index index) | |||
| 310 | return next; | 353 | return next; |
| 311 | } | 354 | } |
| 312 | 355 | ||
| 356 | /* ABQElement -- return pointer to the index'th element in the queue | ||
| 357 | vector. */ | ||
| 358 | static Addr ABQElement(ABQ abq, Index index) { | ||
| 359 | return AddrAdd(abq->queue, index * abq->elementSize); | ||
| 360 | } | ||
| 361 | |||
| 313 | 362 | ||
| 314 | /* C. COPYRIGHT AND LICENSE | 363 | /* C. COPYRIGHT AND LICENSE |
| 315 | * | 364 | * |
diff --git a/mps/code/abq.h b/mps/code/abq.h index e39635dfcaa..085b1ed3d66 100644 --- a/mps/code/abq.h +++ b/mps/code/abq.h | |||
| @@ -1,18 +1,17 @@ | |||
| 1 | /* abq.h: ABQ INTERFACE | 1 | /* abq.h: QUEUE INTERFACE |
| 2 | * | 2 | * |
| 3 | * $Id$ | 3 | * $Id$ |
| 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. |
| 5 | * | 5 | * |
| 6 | * .purpose: A FIFO queue substrate for <code/poolmv2.c> | 6 | * .purpose: A fixed-length FIFO queue. |
| 7 | * | 7 | * |
| 8 | * .source: <design/poolmvt/> | 8 | * .design: <design/abq/> |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #ifndef abq_h | 11 | #ifndef abq_h |
| 12 | #define abq_h | 12 | #define abq_h |
| 13 | 13 | ||
| 14 | #include "meter.h" | 14 | #include "meter.h" |
| 15 | #include "cbs.h" | ||
| 16 | #include "mpm.h" | 15 | #include "mpm.h" |
| 17 | 16 | ||
| 18 | 17 | ||
| @@ -24,17 +23,22 @@ | |||
| 24 | /* Prototypes */ | 23 | /* Prototypes */ |
| 25 | 24 | ||
| 26 | typedef struct ABQStruct *ABQ; | 25 | typedef struct ABQStruct *ABQ; |
| 27 | extern Res ABQInit(Arena arena, ABQ abq, void *owner, Count items); | 26 | typedef Res (*ABQDescribeElement)(Addr element, mps_lib_FILE *stream); |
| 27 | typedef unsigned ABQDisposition; | ||
| 28 | typedef Res (*ABQIterateMethod)(ABQDisposition *dispositionReturn, Addr element, void *closureP); | ||
| 29 | |||
| 30 | extern Res ABQInit(Arena arena, ABQ abq, void *owner, Count elements, Size elementSize); | ||
| 28 | extern Bool ABQCheck(ABQ abq); | 31 | extern Bool ABQCheck(ABQ abq); |
| 29 | extern void ABQFinish(Arena arena, ABQ abq); | 32 | extern void ABQFinish(Arena arena, ABQ abq); |
| 30 | extern Res ABQPush(ABQ abq, CBSBlock block); | 33 | extern Res ABQPush(ABQ abq, Addr element); |
| 31 | extern Res ABQPop(ABQ abq, CBSBlock *blockReturn); | 34 | extern Res ABQPop(ABQ abq, Addr elementReturn); |
| 32 | extern Res ABQPeek(ABQ abq, CBSBlock *blockReturn); | 35 | extern Res ABQPeek(ABQ abq, Addr elementReturn); |
| 33 | extern Res ABQDelete(ABQ abq, CBSBlock block); | 36 | extern Res ABQDelete(ABQ abq, Addr element); |
| 34 | extern Res ABQDescribe(ABQ abq, mps_lib_FILE *stream); | 37 | extern Res ABQDescribe(ABQ abq, ABQDescribeElement describeElement, mps_lib_FILE *stream); |
| 35 | extern Bool ABQIsEmpty(ABQ abq); | 38 | extern Bool ABQIsEmpty(ABQ abq); |
| 36 | extern Bool ABQIsFull(ABQ abq); | 39 | extern Bool ABQIsFull(ABQ abq); |
| 37 | extern Count ABQDepth(ABQ abq); | 40 | extern Count ABQDepth(ABQ abq); |
| 41 | extern void ABQIterate(ABQ abq, ABQIterateMethod iterate, void *closureP); | ||
| 38 | 42 | ||
| 39 | 43 | ||
| 40 | /* Types */ | 44 | /* Types */ |
| @@ -42,9 +46,10 @@ extern Count ABQDepth(ABQ abq); | |||
| 42 | typedef struct ABQStruct | 46 | typedef struct ABQStruct |
| 43 | { | 47 | { |
| 44 | Count elements; | 48 | Count elements; |
| 49 | Size elementSize; | ||
| 45 | Index in; | 50 | Index in; |
| 46 | Index out; | 51 | Index out; |
| 47 | CBSBlock *queue; | 52 | Addr queue; |
| 48 | 53 | ||
| 49 | /* Meter queue depth at each operation */ | 54 | /* Meter queue depth at each operation */ |
| 50 | METER_DECL(push); | 55 | METER_DECL(push); |
| @@ -55,6 +60,12 @@ typedef struct ABQStruct | |||
| 55 | Sig sig; | 60 | Sig sig; |
| 56 | } ABQStruct; | 61 | } ABQStruct; |
| 57 | 62 | ||
| 63 | enum { | ||
| 64 | ABQDispositionKEEP = 1, /* keep item in queue */ | ||
| 65 | ABQDispositionDELETE, /* delete element from queue */ | ||
| 66 | ABQDispositionNONE /* no disposition (error) */ | ||
| 67 | }; | ||
| 68 | |||
| 58 | #endif /* abq_h */ | 69 | #endif /* abq_h */ |
| 59 | 70 | ||
| 60 | 71 | ||
diff --git a/mps/code/abqtest.c b/mps/code/abqtest.c index 7de0ee537a7..f1685cde4b7 100644 --- a/mps/code/abqtest.c +++ b/mps/code/abqtest.c | |||
| @@ -41,54 +41,42 @@ static unsigned popee = 1; | |||
| 41 | static unsigned deleted = 0; | 41 | static unsigned deleted = 0; |
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | typedef struct TestStruct *Test; | 44 | typedef struct TestBlockStruct *TestBlock; |
| 45 | 45 | ||
| 46 | typedef struct TestStruct | 46 | typedef struct TestBlockStruct |
| 47 | { | 47 | { |
| 48 | Test next; | 48 | TestBlock next; |
| 49 | unsigned id; | 49 | unsigned id; |
| 50 | CBSBlockStruct cbsBlockStruct; | 50 | Addr base; |
| 51 | } TestStruct; | 51 | Addr limit; |
| 52 | } TestBlockStruct; | ||
| 52 | 53 | ||
| 53 | 54 | ||
| 54 | static CBSBlock TestCBSBlock(Test t) | 55 | static TestBlock testBlocks = NULL; |
| 55 | { | ||
| 56 | return &t->cbsBlockStruct; | ||
| 57 | } | ||
| 58 | |||
| 59 | static Test CBSBlockTest(CBSBlock c) | ||
| 60 | { | ||
| 61 | return PARENT(TestStruct, cbsBlockStruct, c); | ||
| 62 | } | ||
| 63 | |||
| 64 | 56 | ||
| 65 | static Test testBlocks = NULL; | ||
| 66 | 57 | ||
| 67 | 58 | static TestBlock CreateTestBlock(unsigned no) | |
| 68 | static CBSBlock CreateCBSBlock(unsigned no) | ||
| 69 | { | 59 | { |
| 70 | Test b = malloc(sizeof(TestStruct)); | 60 | TestBlock b = malloc(sizeof(TestBlockStruct)); |
| 71 | cdie(b != NULL, "malloc"); | 61 | cdie(b != NULL, "malloc"); |
| 72 | 62 | ||
| 73 | b->next = testBlocks; | 63 | b->next = testBlocks; |
| 74 | b->id = no; | 64 | b->id = no; |
| 75 | b->cbsBlockStruct.base = 0; | 65 | b->base = 0; |
| 76 | b->cbsBlockStruct.limit = 0; | 66 | b->limit = 0; |
| 77 | 67 | ||
| 78 | testBlocks = b; | 68 | testBlocks = b; |
| 79 | 69 | ||
| 80 | return TestCBSBlock(b); | 70 | return b; |
| 81 | } | 71 | } |
| 82 | 72 | ||
| 83 | 73 | ||
| 84 | static void DestroyCBSBlock(CBSBlock c) | 74 | static void DestroyTestBlock(TestBlock b) |
| 85 | { | 75 | { |
| 86 | Test b = CBSBlockTest(c); | ||
| 87 | |||
| 88 | if (b == testBlocks) | 76 | if (b == testBlocks) |
| 89 | testBlocks = b->next; | 77 | testBlocks = b->next; |
| 90 | else { | 78 | else { |
| 91 | Test prev; | 79 | TestBlock prev; |
| 92 | 80 | ||
| 93 | for (prev = testBlocks; prev != 0; prev = prev->next) | 81 | for (prev = testBlocks; prev != 0; prev = prev->next) |
| 94 | if (prev->next == b) { | 82 | if (prev->next == b) { |
| @@ -104,12 +92,13 @@ static void DestroyCBSBlock(CBSBlock c) | |||
| 104 | static void step(void) | 92 | static void step(void) |
| 105 | { | 93 | { |
| 106 | Res res; | 94 | Res res; |
| 107 | CBSBlock a; | 95 | TestBlock a; |
| 108 | 96 | ||
| 109 | switch (abqRnd(9)) { | 97 | switch (abqRnd(9)) { |
| 110 | case 0: case 1: case 2: case 3: | 98 | case 0: case 1: case 2: case 3: |
| 111 | push: | 99 | push: |
| 112 | res = ABQPush(&abq, CreateCBSBlock(pushee)); | 100 | a = CreateTestBlock(pushee); |
| 101 | res = ABQPush(&abq, (Addr)&a); | ||
| 113 | if (res != ResOK) { | 102 | if (res != ResOK) { |
| 114 | goto pop; | 103 | goto pop; |
| 115 | } | 104 | } |
| @@ -117,7 +106,7 @@ static void step(void) | |||
| 117 | break; | 106 | break; |
| 118 | case 5: case 6: case 7: case 8: | 107 | case 5: case 6: case 7: case 8: |
| 119 | pop: | 108 | pop: |
| 120 | res = ABQPop(&abq, &a); | 109 | res = ABQPop(&abq, (Addr)&a); |
| 121 | if (res != ResOK){ | 110 | if (res != ResOK){ |
| 122 | goto push; | 111 | goto push; |
| 123 | } | 112 | } |
| @@ -125,20 +114,20 @@ static void step(void) | |||
| 125 | popee++; | 114 | popee++; |
| 126 | deleted = 0; | 115 | deleted = 0; |
| 127 | } | 116 | } |
| 128 | cdie(CBSBlockTest(a)->id == popee, "pop"); | 117 | cdie(a->id == popee, "pop"); |
| 129 | popee++; | 118 | popee++; |
| 130 | DestroyCBSBlock(a); | 119 | DestroyTestBlock(a); |
| 131 | break; | 120 | break; |
| 132 | default: | 121 | default: |
| 133 | if (!deleted & (pushee > popee)) { | 122 | if (!deleted & (pushee > popee)) { |
| 134 | Test b; | 123 | TestBlock b; |
| 135 | 124 | ||
| 136 | deleted = (unsigned)abqRnd (pushee - popee) + popee; | 125 | deleted = (unsigned)abqRnd (pushee - popee) + popee; |
| 137 | for (b = testBlocks; b != NULL; b = b->next) | 126 | for (b = testBlocks; b != NULL; b = b->next) |
| 138 | if (b->id == deleted) | 127 | if (b->id == deleted) |
| 139 | break; | 128 | break; |
| 140 | cdie(b != NULL, "found to delete"); | 129 | cdie(b != NULL, "found to delete"); |
| 141 | res = ABQDelete(&abq, TestCBSBlock(b)); | 130 | res = ABQDelete(&abq, (Addr)&b); |
| 142 | cdie(res == ResOK, "ABQDelete"); | 131 | cdie(res == ResOK, "ABQDelete"); |
| 143 | } | 132 | } |
| 144 | } | 133 | } |
| @@ -159,7 +148,7 @@ extern int main(int argc, char *argv[]) | |||
| 159 | die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), | 148 | die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), |
| 160 | "mps_arena_create"); | 149 | "mps_arena_create"); |
| 161 | 150 | ||
| 162 | die(ABQInit((Arena)arena, &abq, NULL, ABQ_SIZE), | 151 | die(ABQInit((Arena)arena, &abq, NULL, ABQ_SIZE, sizeof(TestBlock)), |
| 163 | "ABQInit"); | 152 | "ABQInit"); |
| 164 | 153 | ||
| 165 | abqSize = ABQ_SIZE; | 154 | abqSize = ABQ_SIZE; |