]> gitweb.ps.run Git - onefile/blob - smartptrs.c
add smartptrs.c
[onefile] / smartptrs.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <time.h>
4
5 typedef struct Ptr *Ptr;
6 typedef struct Ref *Ref;
7
8 typedef struct Ptr
9 {
10     Ref ref;
11     Ptr next, prev;
12 } *Ptr;
13 typedef struct Ref
14 {
15     int *data;
16     Ptr head, tail;
17 } *Ref;
18
19 Ref ref_new(int value)
20 {
21     Ref result = malloc(sizeof(struct Ref));
22
23     result->data = malloc(sizeof(int));
24     *result->data = value;
25
26     result->head = result->tail = NULL;
27
28     return result;
29 }
30
31 Ref ref_move(Ref ref)
32 {
33     Ref result = malloc(sizeof(struct Ref));
34
35     result->data = ref->data;
36
37     result->head = ref->head;
38     result->tail = ref->tail;
39
40     for (Ptr p = ref->head; p != NULL; p = p->next)
41     {
42         p->ref = result;
43     }
44     free(ref);
45     return result;
46 }
47
48 void ref_add_ptr(Ref ref, Ptr ptr)
49 {
50     if (ref->head == NULL)
51     {
52         ref->head = ptr;
53         ref->tail = ptr;
54         ptr->next = ptr->prev = NULL;
55         return;
56     }
57     ref->tail->next = ptr;
58     ptr->prev = ref->tail;
59     ptr->next = NULL;
60     ref->tail = ptr;
61 }
62
63 void ref_remove_ptr(Ref ref, Ptr ptr)
64 {
65     for (Ptr p = ref->head; p != NULL; p = p->next)
66     {
67         if (p == ptr)
68         {
69             if (p->prev == NULL)
70                 ref->head = p->next;
71             else
72                 p->prev->next = p->next;
73
74             if (p->next == NULL)
75                 ref->tail = p->prev;
76             else
77                 p->next->prev = p->prev;
78
79             return;
80         }
81     }
82 }
83
84 void ref_free(Ref ref)
85 {
86     for (Ptr p = ref->head; p != NULL; p = p->next)
87     {
88         p->ref = NULL;
89     }
90     free(ref->data);
91     free(ref);
92 }
93
94 Ptr ptr_new(Ref ref)
95 {
96     Ptr result = malloc(sizeof(struct Ptr));
97
98     result->ref = ref;
99
100     ref_add_ptr(ref, result);
101
102     return result;
103 }
104
105 int ptr_get(Ptr ptr)
106 {
107     if (ptr->ref != NULL)
108         return *ptr->ref->data;
109     return 0;
110 }
111
112 void ptr_free(Ptr ptr)
113 {
114     if (ptr->ref != NULL)
115         ref_remove_ptr(ptr->ref, ptr);
116     free(ptr);
117 }
118
119 void test_ref()
120 {
121     Ref r1 = ref_new(123);
122
123     Ptr p1 = ptr_new(r1);
124     Ptr p2 = ptr_new(r1);
125     Ptr p3 = ptr_new(r1);
126     Ptr p4 = ptr_new(r1);
127
128     Ref r2 = ref_move(r1);
129
130     int i = ptr_get(p1) + ptr_get(p2) + ptr_get(p3) + ptr_get(p4);
131
132     ptr_free(p1);
133     ptr_free(p2);
134
135     ref_free(r2);
136
137     ptr_free(p3);
138     ptr_free(p4);
139 }
140
141 void test_reg()
142 {
143     int *r1 = malloc(sizeof(int));
144     *r1 = 123;
145
146     int *p1 = r1;
147     int *p2 = r1;
148     int *p3 = r1;
149     int *p4 = r1;
150
151     int i = *p1 + *p2 + *p3 + *p4;
152
153     int *r2 = r1;
154     r1 = NULL;
155
156     free(r2);
157 }
158
159 int main(int argc, char **argv)
160 {
161     const long N = 1000000;
162
163     clock_t start, end;
164
165     start = clock();
166     for (long i = 0; i < N; i++)
167         test_ref();
168     end = clock();
169     printf("ref: %fms\n", ((double)(end - start)) / CLOCKS_PER_SEC * 1000);
170
171     start = clock();
172     for (long i = 0; i < N; i++)
173         test_reg();
174     end = clock();
175     printf("reg: %fms\n", ((double)(end - start)) / CLOCKS_PER_SEC * 1000);
176
177     return 0;
178 }