+
+/*
+=item im_context_slot_new(destructor)
+
+Allocate a new context-local-storage slot.
+
+=cut
+*/
+
+im_slot_t
+im_context_slot_new(im_slot_destroy_t destructor) {
+ im_slot_t new_slot;
+ im_slot_destroy_t *new_destructors;
+ if (!slot_mutex)
+ slot_mutex = i_mutex_new();
+
+ i_mutex_lock(slot_mutex);
+
+ new_slot = slot_count++;
+ new_destructors = realloc(slot_destructors, sizeof(void *) * slot_count);
+ if (!new_destructors)
+ i_fatal(1, "Cannot allocate memory for slot destructors");
+ slot_destructors = new_destructors;
+
+ slot_destructors[new_slot] = destructor;
+
+ i_mutex_unlock(slot_mutex);
+
+ return new_slot;
+}
+
+/*
+=item im_context_slot_set(slot, value)
+
+Set the value of a slot.
+
+Returns true on success.
+
+Aborts if the slot supplied is invalid.
+
+If reallocation of slot storage fails, returns false.
+
+=cut
+*/
+
+int
+im_context_slot_set(im_context_t ctx, im_slot_t slot, void *value) {
+ if (slot < 0 || slot >= slot_count) {
+ fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
+ (int)slot, (int)slot_count-1);
+ abort();
+ }
+
+ if (slot >= ctx->slot_alloc) {
+ ssize_t i;
+ size_t new_alloc = slot_count;
+ void **new_slots = realloc(ctx->slots, sizeof(void *) * new_alloc);
+
+ if (!new_slots)
+ return 0;
+
+ for (i = ctx->slot_alloc; i < new_alloc; ++i)
+ new_slots[i] = NULL;
+
+ ctx->slots = new_slots;
+ ctx->slot_alloc = new_alloc;
+ }
+
+ ctx->slots[slot] = value;
+
+ return 1;
+}
+
+/*
+=item im_context_slot_get(ctx, slot)
+
+Retrieve the value previously stored in the given slot of the context
+object.
+
+=cut
+*/
+
+void *
+im_context_slot_get(im_context_t ctx, im_slot_t slot) {
+ if (slot < 0 || slot >= slot_count) {
+ fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
+ (int)slot, (int)slot_count-1);
+ abort();
+ }
+
+ if (slot >= ctx->slot_alloc)
+ return NULL;
+
+ return ctx->slots[slot];
+}