blob: ac08a40954215747c5ce763d695922db094f0857 (
plain)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/* Test basic Objective-C foreach syntax. This tests the mutation.
*/
/* { dg-do compile } */
/* FIXME: This test should be run, and it succeeds if the program
aborts at the right time (when the mutation happens). It currently
works, but how do we tell the testsuite to test for it ?
*/
#import "../objc-obj-c++-shared/Object1.h"
#import "../objc-obj-c++-shared/next-mapping.h"
#ifndef __NEXT_RUNTIME__
#include <objc/NXConstStr.h>
#endif
extern int printf (const char *, ...);
#include <stdlib.h>
/*
struct __objcFastEnumerationState
{
unsigned long state;
id *itemsPtr;
unsigned long *mutationsPtr;
unsigned long extra[5];
};
*/
/* A mini-array implementation that can be used to test fast
enumeration. You create the array with some objects; you can
mutate the array, and you can fast-enumerate it.
*/
@interface MyArray : Object
{
unsigned int length;
id *objects;
unsigned long mutated;
}
- (id) initWithLength: (unsigned int)l objects: (id *)o;
- (void) mutate;
- (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state
objects:(id *)stackbuf
count:(unsigned long)len;
@end
@implementation MyArray : Object
- (id) initWithLength: (unsigned int)l
objects: (id *)o
{
length = l;
objects = o;
mutated = 0;
return self;
}
- (void) mutate
{
mutated = 1;
}
- (unsigned long)countByEnumeratingWithState: (struct __objcFastEnumerationState*)state
objects: (id*)stackbuf
count: (unsigned long)len
{
unsigned long i, batch_size;
/* Change the mutationsPtr if 'mutate' is called. */
state->mutationsPtr = &mutated;
/* We keep how many objects we served in the state->state counter. So the next batch
will contain up to length - state->state objects. */
batch_size = length - state->state;
/* Make obvious adjustments. */
if (batch_size < 0)
batch_size = 0;
if (batch_size > len)
batch_size = len;
/* Copy the objects. */
for (i = 0; i < batch_size; i++)
stackbuf[i] = objects[i];
state->state += batch_size;
state->itemsPtr = stackbuf;
return batch_size;
}
@end
int main (void)
{
MyArray *array;
Object *object;
int counter, i;
id *objects;
/* Test iterating over 20 objects, mutating after 15. */
objects = malloc (sizeof (id) * 20);
for (i = 0; i < 20; i++)
objects[i] = @"object";
array = [[MyArray alloc] initWithLength: 20
objects: objects];
counter = 0;
for (object in array)
{
counter++;
printf ("%d\n", counter);
if (counter == 14)
{
printf ("Mutating (should abort at next iteration)\n");
[array mutate];
}
}
return 0;
}
|