00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "dbus-dataslot.h"
00024
#include "dbus-threads.h"
00025
00043
dbus_bool_t
00044 _dbus_data_slot_allocator_init (
DBusDataSlotAllocator *allocator)
00045 {
00046 allocator->
allocated_slots =
NULL;
00047 allocator->
n_allocated_slots = 0;
00048 allocator->
n_used_slots = 0;
00049 allocator->
lock =
NULL;
00050
00051
return TRUE;
00052 }
00053
00066
dbus_bool_t
00067 _dbus_data_slot_allocator_alloc (
DBusDataSlotAllocator *allocator,
00068 DBusMutex *mutex,
00069 dbus_int32_t *slot_id_p)
00070 {
00071
dbus_int32_t slot;
00072
00073
if (!
dbus_mutex_lock (mutex))
00074
return FALSE;
00075
00076
if (allocator->
n_allocated_slots == 0)
00077 {
00078
_dbus_assert (allocator->
lock ==
NULL);
00079 allocator->
lock = mutex;
00080 }
00081
else
00082
_dbus_assert (allocator->
lock == mutex);
00083
00084
if (*slot_id_p >= 0)
00085 {
00086 slot = *slot_id_p;
00087
00088
_dbus_assert (slot < allocator->n_allocated_slots);
00089
_dbus_assert (allocator->
allocated_slots[slot].
slot_id == slot);
00090
00091 allocator->
allocated_slots[slot].
refcount += 1;
00092
00093
goto out;
00094 }
00095
00096
_dbus_assert (*slot_id_p < 0);
00097
00098
if (allocator->
n_used_slots < allocator->
n_allocated_slots)
00099 {
00100 slot = 0;
00101
while (slot < allocator->
n_allocated_slots)
00102 {
00103
if (allocator->
allocated_slots[slot].
slot_id < 0)
00104 {
00105 allocator->
allocated_slots[slot].
slot_id = slot;
00106 allocator->
allocated_slots[slot].
refcount = 1;
00107 allocator->
n_used_slots += 1;
00108
break;
00109 }
00110 ++slot;
00111 }
00112
00113
_dbus_assert (slot < allocator->n_allocated_slots);
00114 }
00115
else
00116 {
00117
DBusAllocatedSlot *tmp;
00118
00119 slot = -1;
00120 tmp =
dbus_realloc (allocator->
allocated_slots,
00121 sizeof (
DBusAllocatedSlot) * (allocator->
n_allocated_slots + 1));
00122
if (tmp ==
NULL)
00123
goto out;
00124
00125 allocator->
allocated_slots = tmp;
00126 slot = allocator->
n_allocated_slots;
00127 allocator->
n_allocated_slots += 1;
00128 allocator->
n_used_slots += 1;
00129 allocator->
allocated_slots[slot].
slot_id = slot;
00130 allocator->
allocated_slots[slot].
refcount = 1;
00131 }
00132
00133
_dbus_assert (slot >= 0);
00134
_dbus_assert (slot < allocator->n_allocated_slots);
00135
_dbus_assert (*slot_id_p < 0);
00136
_dbus_assert (allocator->
allocated_slots[slot].
slot_id == slot);
00137
_dbus_assert (allocator->
allocated_slots[slot].
refcount == 1);
00138
00139 *slot_id_p = slot;
00140
00141 _dbus_verbose (
"Allocated slot %d on allocator %p total %d slots allocated %d used\n",
00142 slot, allocator, allocator->
n_allocated_slots, allocator->
n_used_slots);
00143
00144 out:
00145
dbus_mutex_unlock (allocator->
lock);
00146
return slot >= 0;
00147 }
00148
00160
void
00161 _dbus_data_slot_allocator_free (
DBusDataSlotAllocator *allocator,
00162 dbus_int32_t *slot_id_p)
00163 {
00164
dbus_mutex_lock (allocator->
lock);
00165
00166
_dbus_assert (*slot_id_p < allocator->n_allocated_slots);
00167
_dbus_assert (allocator->
allocated_slots[*slot_id_p].
slot_id == *slot_id_p);
00168
_dbus_assert (allocator->
allocated_slots[*slot_id_p].
refcount > 0);
00169
00170 allocator->
allocated_slots[*slot_id_p].
refcount -= 1;
00171
00172
if (allocator->
allocated_slots[*slot_id_p].
refcount > 0)
00173 {
00174
dbus_mutex_unlock (allocator->
lock);
00175
return;
00176 }
00177
00178
00179 _dbus_verbose (
"Freeing slot %d on allocator %p total %d allocated %d used\n",
00180 *slot_id_p, allocator, allocator->
n_allocated_slots, allocator->
n_used_slots);
00181
00182 allocator->
allocated_slots[*slot_id_p].
slot_id = -1;
00183 *slot_id_p = -1;
00184
00185 allocator->
n_used_slots -= 1;
00186
00187
if (allocator->
n_used_slots == 0)
00188 {
00189 DBusMutex *mutex = allocator->
lock;
00190
00191
dbus_free (allocator->
allocated_slots);
00192 allocator->
allocated_slots =
NULL;
00193 allocator->
n_allocated_slots = 0;
00194 allocator->
lock =
NULL;
00195
00196
dbus_mutex_unlock (mutex);
00197 }
00198
else
00199 {
00200
dbus_mutex_unlock (allocator->
lock);
00201 }
00202 }
00203
00208
void
00209 _dbus_data_slot_list_init (
DBusDataSlotList *list)
00210 {
00211 list->
slots =
NULL;
00212 list->
n_slots = 0;
00213 }
00214
00232
dbus_bool_t
00233 _dbus_data_slot_list_set (
DBusDataSlotAllocator *allocator,
00234
DBusDataSlotList *list,
00235
int slot,
00236
void *data,
00237 DBusFreeFunction free_data_func,
00238 DBusFreeFunction *old_free_func,
00239
void **old_data)
00240 {
00241
#ifndef DBUS_DISABLE_ASSERT
00242
00243
00244
00245
00246
if (!
dbus_mutex_lock (allocator->
lock))
00247
return FALSE;
00248
_dbus_assert (slot < allocator->n_allocated_slots);
00249
_dbus_assert (allocator->
allocated_slots[slot].
slot_id == slot);
00250
dbus_mutex_unlock (allocator->
lock);
00251
#endif
00252
00253
if (slot >= list->
n_slots)
00254 {
00255
DBusDataSlot *tmp;
00256
int i;
00257
00258 tmp =
dbus_realloc (list->
slots,
00259 sizeof (
DBusDataSlot) * (slot + 1));
00260
if (tmp ==
NULL)
00261
return FALSE;
00262
00263 list->
slots = tmp;
00264 i = list->
n_slots;
00265 list->
n_slots = slot + 1;
00266
while (i < list->
n_slots)
00267 {
00268 list->
slots[i].
data =
NULL;
00269 list->
slots[i].
free_data_func =
NULL;
00270 ++i;
00271 }
00272 }
00273
00274
_dbus_assert (slot < list->n_slots);
00275
00276 *old_data = list->
slots[slot].
data;
00277 *old_free_func = list->
slots[slot].
free_data_func;
00278
00279 list->
slots[slot].
data = data;
00280 list->
slots[slot].
free_data_func = free_data_func;
00281
00282
return TRUE;
00283 }
00284
00294
void*
00295 _dbus_data_slot_list_get (
DBusDataSlotAllocator *allocator,
00296
DBusDataSlotList *list,
00297
int slot)
00298 {
00299
#ifndef DBUS_DISABLE_ASSERT
00300
00301
00302
00303
00304
if (!
dbus_mutex_lock (allocator->
lock))
00305
return FALSE;
00306
_dbus_assert (slot >= 0);
00307
_dbus_assert (slot < allocator->n_allocated_slots);
00308
_dbus_assert (allocator->
allocated_slots[slot].
slot_id == slot);
00309
dbus_mutex_unlock (allocator->
lock);
00310
#endif
00311
00312
if (slot >= list->
n_slots)
00313
return NULL;
00314
else
00315
return list->
slots[slot].
data;
00316 }
00317
00325
void
00326 _dbus_data_slot_list_free (
DBusDataSlotList *list)
00327 {
00328
int i;
00329
00330 i = 0;
00331
while (i < list->
n_slots)
00332 {
00333
if (list->
slots[i].
free_data_func)
00334 (* list->
slots[i].
free_data_func) (list->
slots[i].
data);
00335 list->
slots[i].
data =
NULL;
00336 list->
slots[i].
free_data_func =
NULL;
00337 ++i;
00338 }
00339
00340
dbus_free (list->
slots);
00341 list->
slots =
NULL;
00342 list->
n_slots = 0;
00343 }
00344
00347
#ifdef DBUS_BUILD_TESTS
00348
#include "dbus-test.h"
00349
#include <stdio.h>
00350
00351
static int free_counter;
00352
00353
static void
00354 test_free_slot_data_func (
void *data)
00355 {
00356
int i =
_DBUS_POINTER_TO_INT (data);
00357
00358
_dbus_assert (free_counter == i);
00359 ++free_counter;
00360 }
00361
00365
dbus_bool_t
00366 _dbus_data_slot_test (
void)
00367 {
00368
DBusDataSlotAllocator allocator;
00369
DBusDataSlotList list;
00370
int i;
00371
DBusFreeFunction old_free_func;
00372
void *old_data;
00373 DBusMutex *mutex;
00374
00375
if (!
_dbus_data_slot_allocator_init (&allocator))
00376
_dbus_assert_not_reached (
"no memory for allocator");
00377
00378
_dbus_data_slot_list_init (&list);
00379
00380 mutex =
dbus_mutex_new ();
00381
if (mutex ==
NULL)
00382
_dbus_assert_not_reached (
"failed to alloc mutex");
00383
00384
#define N_SLOTS 100
00385
00386 i = 0;
00387
while (i < N_SLOTS)
00388 {
00389
00390
00391
00392
00393
dbus_int32_t tmp = -1;
00394
00395
_dbus_data_slot_allocator_alloc (&allocator, mutex, &tmp);
00396
00397
if (tmp != i)
00398
_dbus_assert_not_reached (
"did not allocate slots in numeric order\n");
00399
00400 ++i;
00401 }
00402
00403 i = 0;
00404
while (i < N_SLOTS)
00405 {
00406
if (!
_dbus_data_slot_list_set (&allocator, &list,
00407 i,
00408 _DBUS_INT_TO_POINTER (i),
00409 test_free_slot_data_func,
00410 &old_free_func, &old_data))
00411
_dbus_assert_not_reached (
"no memory to set data");
00412
00413
_dbus_assert (old_free_func == NULL);
00414
_dbus_assert (old_data == NULL);
00415
00416
_dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) ==
00417 _DBUS_INT_TO_POINTER (i));
00418
00419 ++i;
00420 }
00421
00422 free_counter = 0;
00423 i = 0;
00424
while (i < N_SLOTS)
00425 {
00426
if (!
_dbus_data_slot_list_set (&allocator, &list,
00427 i,
00428 _DBUS_INT_TO_POINTER (i),
00429 test_free_slot_data_func,
00430 &old_free_func, &old_data))
00431
_dbus_assert_not_reached (
"no memory to set data");
00432
00433
_dbus_assert (old_free_func == test_free_slot_data_func);
00434
_dbus_assert (_DBUS_POINTER_TO_INT (old_data) == i);
00435
00436 (* old_free_func) (old_data);
00437
_dbus_assert (i == (free_counter - 1));
00438
00439
_dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) ==
00440 _DBUS_INT_TO_POINTER (i));
00441
00442 ++i;
00443 }
00444
00445 free_counter = 0;
00446
_dbus_data_slot_list_free (&list);
00447
00448
_dbus_assert (N_SLOTS == free_counter);
00449
00450 i = 0;
00451
while (i < N_SLOTS)
00452 {
00453
dbus_int32_t tmp = i;
00454
00455
_dbus_data_slot_allocator_free (&allocator, &tmp);
00456
_dbus_assert (tmp == -1);
00457 ++i;
00458 }
00459
00460
dbus_mutex_free (mutex);
00461
00462
return TRUE;
00463 }
00464
00465
#endif