diff options
| author | Gareth Rees | 2013-05-20 20:40:16 +0100 |
|---|---|---|
| committer | Gareth Rees | 2013-05-20 20:40:16 +0100 |
| commit | df1a8a3807db2d085e668aa625a0734d79e46eec (patch) | |
| tree | ab1dcfa387c85deb775b777df5963806460f9696 /mps/code | |
| parent | 217831cc47e7b2a4c02513cd8f3dddf32604faa5 (diff) | |
| download | emacs-df1a8a3807db2d085e668aa625a0734d79e46eec.tar.gz emacs-df1a8a3807db2d085e668aa625a0734d79e46eec.zip | |
Make the abq module manage elements of arbitrary type (knowing only their address and size) instead of managing cbsblock only. (this is preparatory to removing cbsblock from the cbs public interface.)
Update abqtest to use the new interface.
Add ABQ design.
Copied from Perforce
Change: 182013
ServerID: perforce.ravenbrook.com
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; |