Objectively
Ultra-lightweight object oriented framework for GNU C.
Loading...
Searching...
No Matches
Class.c
Go to the documentation of this file.
1/*
2 * Objectively: Ultra-lightweight object oriented framework for GNU C.
3 * Copyright (C) 2014 Jay Dolan <jay@jaydolan.com>
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 *
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 *
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24#include "Config.h"
25
26#include <assert.h>
27#include <dlfcn.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31
32#if HAVE_UNISTD_H
33#include <unistd.h>
34#endif
35
36#include "Class.h"
37#include "Object.h"
38
39size_t _pageSize;
40
42
46static void teardown(void) {
47 Class *c;
48
49 c = _classes;
50 while (c) {
51 if (c->def.destroy) {
52 c->def.destroy(c);
53 }
54
55 c = c->next;
56 }
57
58 c = _classes;
59 while (c) {
60
61 Class *next = c->next;
62
63 free(c->interface);
64 free(c);
65
66 c = next;
67 }
68}
69
73static void setup(void) {
74
75 _classes = NULL;
76
77#if !defined(_SC_PAGESIZE)
78 _pageSize = 4096;
79#else
80 _pageSize = sysconf(_SC_PAGESIZE);
81#endif
82
83 atexit(teardown);
84}
85
87
88 static Once once;
89 do_once(&once, setup());
90
91 assert(def);
92 assert(def->name);
93 assert(def->instanceSize);
94 assert(def->interfaceSize);
95 assert(def->interfaceOffset);
96
97 Class *clazz = calloc(1, sizeof(Class));
98 assert(clazz);
99
100 clazz->def = *def;
101
102 clazz->interface = calloc(1, def->interfaceSize);
103 assert(clazz->interface);
104
105 Class *superclass = clazz->def.superclass;
106 if (superclass) {
107
108 assert(superclass->def.instanceSize <= def->instanceSize);
109 assert(superclass->def.interfaceSize <= def->interfaceSize);
110
111 memcpy(clazz->interface, superclass->interface, superclass->def.interfaceSize);
112 }
113
114 if (clazz->def.initialize) {
115 clazz->def.initialize(clazz);
116 }
117
118 clazz->next = __sync_lock_test_and_set(&_classes, clazz);
119
120 return clazz;
121}
122
124
125 ident obj = calloc(1, clazz->def.instanceSize);
126 assert(obj);
127
128 Object *object = (Object *) obj;
129
130 object->magic = OBJECTIVELY_MAGIC;
131 object->clazz = clazz;
132 object->referenceCount = 1;
133
134 ident interface = clazz->interface;
135 do {
136 *(ident *) (obj + clazz->def.interfaceOffset) = interface;
137 } while ((clazz = clazz->def.superclass));
138
139 return obj;
140}
141
142ident _cast(const Class *clazz, const ident obj) {
143
144 if (obj) {
145 const Class *c = ((Object *) obj)->clazz;
146 while (c) {
147
148 // as a special case, we optimize for _Object
149 if (c == clazz || clazz == _Object()) {
150 break;
151 }
152
153 c = c->def.superclass;
154 }
155 assert(c);
156 }
157
158 return (ident) obj;
159}
160
161Class *classForName(const char *name) {
162
163 if (name) {
164 Class *c = _classes;
165 while (c) {
166 if (strcmp(name, c->def.name) == 0) {
167 return c;
168 }
169 c = c->next;
170 }
171
172 char *s;
173 if (asprintf(&s, "_%s", name) > 0) {
174 Class *clazz = NULL;
175#if defined(_WIN32)
176 static Once once;
177 static ident handle;
178 do_once(&once, { handle = dlopen(NULL, RTLD_LAZY); });
179 Class *(*archetype)(void) = handle ? dlsym(handle, s) : NULL;
180#else
181 Class *(*archetype)(void) = dlsym(RTLD_DEFAULT, s);
182#endif
183 if (archetype) {
184 clazz = archetype();
185 }
186
187 free(s);
188 return clazz;
189 }
190 }
191
192 return NULL;
193}
194
196
197 if (obj) {
198 Object *object = cast(Object, obj);
199
200 assert(object);
201
202 if (__sync_add_and_fetch(&object->referenceCount, -1) == 0) {
203 $(object, dealloc);
204 }
205 }
206
207 return NULL;
208}
209
211
212 Object *object = cast(Object, obj);
213
214 assert(object);
215
216 __sync_add_and_fetch(&object->referenceCount, 1);
217
218 return obj;
219}
static void dealloc(Object *self)
Definition Array.c:99
static void teardown(void)
Called atexit to teardown Objectively.
Definition Class.c:46
ident _alloc(Class *clazz)
Instantiate a type through the given Class.
Definition Class.c:123
static void setup(void)
Called when initializing Object to setup Objectively.
Definition Class.c:73
size_t _pageSize
Definition Class.c:39
Class * classForName(const char *name)
Definition Class.c:161
ident release(ident obj)
Atomically decrement the given Object's reference count. If the resulting reference count is 0,...
Definition Class.c:195
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition Class.c:86
static Class * _classes
Definition Class.c:41
ident retain(ident obj)
Atomically increment the given Object's reference count.
Definition Class.c:210
ident _cast(const Class *clazz, const ident obj)
Perform a type-checking cast.
Definition Class.c:142
Classes describe the state and behavior of an Objectively type.
#define obj
#define cast(type, obj)
Safely cast obj to type.
Definition Class.h:182
#define OBJECTIVELY_MAGIC
The header value identifying Objectively types.
Definition Class.h:159
Class * _Object(void)
Definition Object.c:136
Object is the root Class of The Objectively Class hierarchy.
UTF-8 strings.
static Unicode next(StringReader *self, StringReaderMode mode)
void * ident
The identity type, similar to Objective-C id.
Definition Types.h:49
long Once
The Once type.
Definition Once.h:37
#define do_once(once, block)
Executes the given block at most one time.
Definition Once.h:43
ClassDefs are passed to _initialize via an archetype to initialize a Class.
Definition Class.h:41
size_t instanceSize
The instance size (required).
Definition Class.h:69
size_t interfaceSize
The interface size (required).
Definition Class.h:79
ptrdiff_t interfaceOffset
The interface offset (required).
Definition Class.h:74
Class * superclass
The superclass (required). e.g. _Object().
Definition Class.h:89
void(* destroy)(Class *clazz)
The Class destructor (optional). This method is run for initialized Classes when your application exi...
Definition Class.h:47
const char * name
The Class name (required).
Definition Class.h:84
void(* initialize)(Class *clazz)
The Class initializer (optional).
Definition Class.h:64
The runtime representation of a Class.
Definition Class.h:95
ClassDef def
The Class definition.
Definition Class.h:100
Class * next
Provides chaining of initialized Classes.
Definition Class.h:110
ident interface
The interface of the Class.
Definition Class.h:105
Object is the root Class of The Objectively Class hierarchy.
Definition Object.h:46
unsigned int magic
A header to allow introspection of Object types.
Definition Object.h:50