design_pattern_for_c  V 1.00
flyweight.c
Go to the documentation of this file.
1 
5 #include <stdarg.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <pthread.h>
10 #include "flyweight.h"
11 #include "dp_util.h"
12 
13 /*************
14  * public define
15 *************/
17 /* @{ */
18 #define FLYWEIGHT_FAILED (-1)
19 #define FLYWEIGHT_SUCCESS (0)
20 /* @} */
21 
27 
30  void * instance;
31 };
32 
33 /* ! new flyweight_instance_t */
34 static FlyweightInstance flyweight_instance_new(size_t size);
35 /* ! free flyweight_instance_t */
36 static void flyweight_instance_free(FlyweightInstance instance);
37 
42  //private member
44  size_t class_size;
46  pthread_mutex_t *lock;
47 };
48 
50 /* @{ */
60 static FlyweightInstance flyweight_factory_get(FlyweightFactory class_factory, void * constructor_parameter);
61 /* @} */
62 
64 /* @{ */
66 static inline void flyweight_class_default_constructor(void *this, size_t size, void *input_parameter);
68 static inline int flyweight_class_default_equall_operand(void *this, size_t size, void *input_parameter);
70 static inline int flyweight_class_default_setter(void *this, size_t size, void *input_parameter);
73 #define FLYWEIGHT_CLASS_LOCK(instance) DPUTIL_LOCK(instance->lock)
74 #define FLYWEIGHT_CLASS_UNLOCK DPUTIL_UNLOCK
75 /* @} */
76 
77 /*************
78  * for FlyweightInstance API
79 *************/
81 
82  FlyweightInstance instance = (FlyweightInstance )calloc(1, sizeof(struct flyweight_instance_t) );
83  if( !instance ) {
84  return NULL;
85  }
86 
87  //allocate
88  instance->instance = calloc(1, size);
89  if( !instance->instance ) {
90  free(instance);
91  return NULL;
92  }
93 
94  return instance;
95 }
96 
98  if( instance && instance->instance ) {
99  free(instance->instance);
100  }
101  free(instance);
102 }
103 
104 /*************
105  * for FlyweightFactory API
106 *************/
108  //fail safe, if equall_operand == NULL, there is no case to store same instance
109  if( !class_factory->methods.equall_operand ) {
110  DEBUG_ERRPRINT("operand is NULL\n");
111  return NULL;
112  }
113 
114  FlyweightInstance instance = class_factory->class_instances;
115  while(instance) {
116  if( class_factory->methods.equall_operand(instance->instance, class_factory->class_size, constructor_parameter) ) {
117  DEBUG_ERRPRINT("address %p instance is same\n", instance);
118  break;
119  }
120  instance=instance->next;
121  }
122 
123  return instance;
124 }
125 
128  if( !instance ) {
129  return NULL;
130  }
131 
132  if(class_factory->methods.constructor) {
133  class_factory->methods.constructor(instance->instance, class_factory->class_size, constructor_parameter);
134  }
135  return instance;
136 }
137 
139  instance->next = class_factory->class_instances;
140  class_factory->class_instances = instance;
141 }
142 
144  FlyweightInstance instance = class_factory->class_instances;
145  if( instance ) {
146  class_factory->class_instances = class_factory->class_instances->next;
147  }
148 
149  return instance;
150 }
151 
154  if( instance ) {
155  //if already keep method, return it;
156  return instance;
157  }
158 
159  //allocate
160  instance = flyweight_factory_instance_new(class_factory, constructor_parameter);
161  if(instance) {
163  }
164 
165  return instance;
166 }
167 
168 /*private API*/
170 static inline void flyweight_class_default_constructor(void *this, size_t size, void *input_parameter) {
171  if(input_parameter==NULL) {
172  return;
173  }
174 
175  memcpy(this, input_parameter, size);
176 }
177 
179 static inline int flyweight_class_default_equall_operand(void *this, size_t size, void *input_parameter) {
180  if(input_parameter==NULL) {
181  return 0;
182  }
183 
184  return (memcmp(this, input_parameter, size) == 0);
185 }
186 
188 static inline int flyweight_class_default_setter(void *this, size_t size, void *input_parameter) {
189  if(input_parameter==NULL) {
190  return FLYWEIGHT_FAILED;
191  }
192 
193  memcpy(this, input_parameter, size);
194  return FLYWEIGHT_SUCCESS;
195 }
196 
199  if(!methods) {
200  //set default. destrctor is NULL
201  class_factory->methods.constructor = flyweight_class_default_constructor;
202  class_factory->methods.equall_operand = flyweight_class_default_equall_operand;
204  } else {
205  memcpy((void *)&class_factory->methods, (void *)methods, sizeof(class_factory->methods));
206  }
207 }
208 
209 /*************
210  * public interface API implement
211 *************/
212 FlyweightFactory flyweight_factory_new(size_t class_size, int is_threadsafe, FlyweightMethodsIF methods) {
213 
214  if(class_size<=0) {
215  return NULL;
216  }
217 
218  //allocate class_factory
220  if( !class_factory ) {
221  DEBUG_ERRPRINT("calloc instance list error:%s\n", strerror(errno));
222  return NULL;
223  }
224 
225  //when use threadsafe, allocate mutex lock
226  if( is_threadsafe ) {
227  class_factory->lock = (pthread_mutex_t *) calloc(1, sizeof(pthread_mutex_t));
228  if( !class_factory->lock ) {
229  DEBUG_ERRPRINT("class instance lock error:%s\n", strerror(errno));
231  return NULL;
232  }
233 
234  pthread_mutex_init(class_factory->lock, NULL);
235  }
236 
237  class_factory->class_size = class_size;
238  //set methods
240 
241  return class_factory;
242 }
243 
244 void * flyweight_get(FlyweightFactory this, void * constructor_parameter) {
245  //fail safe
246  if(!this) {
247  return NULL;
248  }
249 
250  void *ret=NULL;
251  FLYWEIGHT_CLASS_LOCK(this);
252 
253  //get instance
254  FlyweightInstance instance = flyweight_factory_get(this, constructor_parameter);
255  if( instance ) {
256  ret = instance->instance;
257  }
258 
260 
261  return ret;
262 }
263 
264 int flyweight_set(FlyweightFactory this, void * constructor_parameter, void * data, int (*setter)(void *this, size_t size, void *input_parameter)) {
265 
266  //fail safe
267  if(!this) {
268  return FLYWEIGHT_FAILED;
269  }
270 
271  int ret=FLYWEIGHT_FAILED;
272 
273  FLYWEIGHT_CLASS_LOCK(this);
274 
275  //get and set instance
276  FlyweightInstance instance = flyweight_factory_get(this, constructor_parameter);
277 
278  if(!instance) {
279  DEBUG_ERRPRINT("Failed to get instance! handle[%p]\n", this );
280  } else {
281  if( setter ) {
282  ret = setter(instance->instance, this->class_size, data);
283  } else if ( this->methods.setter ) {
284  ret = this->methods.setter(instance->instance, this->class_size, data);
285  }
286  }
287 
289 
290  return ret;
291 }
292 
294  //fail safe
295  if(!this) {
296  return;
297  }
298 
299  pthread_mutex_t *keep_mutex_for_free=this->lock;
300 
301  FLYWEIGHT_CLASS_LOCK(this);
302 
303  //pop and free
304  FlyweightInstance instance=NULL;
305  while( (instance = flyweight_factory_pop_instance(this)) != NULL ) {
306  //call destcuctor
307  if(this->methods.destructor) {
308  this->methods.destructor(instance->instance);
309  }
310  flyweight_instance_free(instance);
311  }
312  free(this);
313 
314  //initialize
316 
317  //free API care NULL
318  free(keep_mutex_for_free);
319 }
320 
pthread_mutex_t * lock
list of instance
Definition: flyweight.c:46
struct flyweight_factory_t * FlyweightFactory
FlyweightFactory definition.
Definition: flyweight.h:60
static void flyweight_factory_push_instance(FlyweightInstance instance, FlyweightFactory class_factory)
push instance into list.
Definition: flyweight.c:138
static void flyweight_class_default_constructor(void *this, size_t size, void *input_parameter)
Default constructor.
Definition: flyweight.c:170
Utility headers
This is API as Flyweight design petten.
instance data definition.
#define FLYWEIGHT_SUCCESS
Definition: flyweight.c:19
size_t class_size
methods
Definition: flyweight.c:44
#define FLYWEIGHT_CLASS_UNLOCK
Definition: flyweight.c:74
static FlyweightInstance flyweight_factory_get_storaged_instance(FlyweightFactory class_factory, void *constructor_parameter)
Check has instance.
Definition: flyweight.c:107
void(* free)(EventInstance this)
Definition: event_thread.c:39
static void flyweight_class_set_methods(FlyweightMethodsIF methods, FlyweightFactory instance)
Set methods.
Definition: flyweight.c:198
FlyweightFactory member definition, defined in flyweight.c.
Definition: flyweight.c:41
static int flyweight_class_default_equall_operand(void *this, size_t size, void *input_parameter)
Default equall operand.
Definition: flyweight.c:179
struct flyweight_instance_t * FlyweightInstance
Definition: flyweight.c:26
static FlyweightInstance flyweight_instance_new(size_t size)
Definition: flyweight.c:80
static int flyweight_class_default_setter(void *this, size_t size, void *input_parameter)
Default setter.
Definition: flyweight.c:188
int flyweight_set(FlyweightFactory this, void *constructor_parameter, void *data, int(*setter)(void *this, size_t size, void *input_parameter))
setter
Definition: flyweight.c:264
FlyweightInstance class_instances
size of class
Definition: flyweight.c:45
#define FLYWEIGHT_FAILED
Definition: flyweight.c:18
void flyweight_factory_free(FlyweightFactory this)
clear class handle
Definition: flyweight.c:293
static FlyweightInstance flyweight_factory_instance_new(FlyweightFactory class_factory, void *constructor_parameter)
allocate.
Definition: flyweight.c:126
static FlyweightInstance flyweight_factory_pop_instance(FlyweightFactory class_factory)
pop instance from list.
Definition: flyweight.c:143
#define FLYWEIGHT_CLASS_LOCK(instance)
Definition: flyweight.c:73
FlyweightFactory flyweight_factory_new(size_t class_size, int is_threadsafe, FlyweightMethodsIF methods)
define class for flyweight
Definition: flyweight.c:212
static void flyweight_instance_free(FlyweightInstance instance)
Definition: flyweight.c:97
instance data definition, instance storaged by list
Definition: flyweight.c:28
static FlyweightInstance flyweight_factory_get(FlyweightFactory class_factory, void *constructor_parameter)
Getter.
Definition: flyweight.c:152
flyweight_methods_t methods
Definition: flyweight.c:43
void * flyweight_get(FlyweightFactory this, void *constructor_parameter)
getter
Definition: flyweight.c:244
#define DEBUG_ERRPRINT(...)
Definition: dp_debug.h:69
Flyweight methods interface definition, to set flyweight_factory_new.
Definition: flyweight.h:14
FlyweightInstance next
Definition: flyweight.c:29