} tsrm_resource_type;
-#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
-#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
-
/* The memory manager table */
static tsrm_tls_entry **tsrm_tls_table=NULL;
static int tsrm_tls_table_size;
int tsrm_error(int level, const char *format, ...);
/* Read a resource from a thread's resource storage */
-void *ts_resource_read( tsrm_tls_entry *thread_resources, ts_rsrc_id id );
static int tsrm_error_level;
static FILE *tsrm_error_file;
+
#if TSRM_DEBUG
-#define TSRM_ERROR(a) tsrm_error a
-#define TSRM_SAFE_ARRAY_OFFSET(array, offset, range) (((offset)>=0 && (offset)<(range)) ? array[offset] : NULL)
+#define TSRM_ERROR(args) tsrm_error args
+#define TSRM_SAFE_RETURN_RSRC(array, offset, range) \
+ { \
+ int unshuffled_offset = TSRM_UNSHUFFLE_RSRC_ID(offset); \
+ \
+ if (offset==0) { \
+ return &array; \
+ } else if ((unshuffled_offset)>=0 && (unshuffled_offset)<(range)) { \
+ TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Successfully fetched resource id %d for thread id %ld - 0x%0.8X", \
+ unshuffled_offset, (long) thread_resources->thread_id, array[unshuffled_offset])); \
+ return array[unshuffled_offset]; \
+ } else { \
+ TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Resource id %d is out of range (%d..%d)", \
+ unshuffled_offset, TSRM_SHUFFLE_RSRC_ID(0), TSRM_SHUFFLE_RSRC_ID(thread_resources->count-1))); \
+ return NULL; \
+ } \
+ }
#else
-#define TSRM_ERROR(a)
-#define TSRM_SAFE_ARRAY_OFFSET(array, offset, range) array[offset]
+#define TSRM_ERROR
+#define RETURN_TSRM_SAFE_ARRAY_OFFSET(array, offset, range) return array[offset]
#endif
#if defined(PTHREADS)
/* allocates a new thread-safe-resource id */
-TSRM_API ts_rsrc_id ts_allocate_id(size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
+TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
{
- ts_rsrc_id new_id;
int i;
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size));
tsrm_mutex_lock(tsmm_mutex);
/* obtain a resource id */
- new_id = id_count++;
- TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", TSRM_SHUFFLE_RSRC_ID(new_id)));
+ *rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++);
+ TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", *rsrc_id));
/* store the new resource type in the resource sizes table */
if (resource_types_table_size < id_count) {
if (!resource_types_table) {
tsrm_mutex_unlock(tsmm_mutex);
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource"));
+ *rsrc_id = 0;
return 0;
}
resource_types_table_size = id_count;
}
- resource_types_table[new_id].size = size;
- resource_types_table[new_id].ctor = ctor;
- resource_types_table[new_id].dtor = dtor;
+ resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size;
+ resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
+ resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
/* enlarge the arrays for the already active threads */
for (i=0; i<tsrm_tls_table_size; i++) {
for (j=p->count; j<id_count; j++) {
p->storage[j] = (void *) malloc(resource_types_table[j].size);
if (resource_types_table[j].ctor) {
- resource_types_table[j].ctor(p->storage[j]);
+ resource_types_table[j].ctor(p->storage[j], &p->storage);
}
}
p->count = id_count;
}
tsrm_mutex_unlock(tsmm_mutex);
- TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", TSRM_SHUFFLE_RSRC_ID(new_id)));
- return TSRM_SHUFFLE_RSRC_ID(new_id);
+ TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id));
+ return *rsrc_id;
}
for (i=0; i<id_count; i++) {
(*thread_resources_ptr)->storage[i] = (void *) malloc(resource_types_table[i].size);
if (resource_types_table[i].ctor) {
- resource_types_table[i].ctor((*thread_resources_ptr)->storage[i]);
+ resource_types_table[i].ctor((*thread_resources_ptr)->storage[i], &(*thread_resources_ptr)->storage);
}
}
if (!th_id) {
#if defined(PTHREADS)
/* Fast path for looking up the resources for the current
- * thread. Its used by just about every call to
- * ts_resource_ex(). This avoids the need for a mutex lock
- * and our hashtable lookup.
- */
- thread_resources = pthread_getspecific( tls_key );
+ * thread. Its used by just about every call to
+ * ts_resource_ex(). This avoids the need for a mutex lock
+ * and our hashtable lookup.
+ */
+ thread_resources = pthread_getspecific(tls_key);
#elif defined(TSRM_ST)
thread_resources = st_thread_getspecific(tls_key);
#else
thread_resources = NULL;
#endif
if (thread_resources) {
- TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for current thread %d", id, (long) thread_resources->thread_id ));
- return ts_resource_read( thread_resources, id );
+ TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for current thread %d", id, (long) thread_resources->thread_id));
+ /* Read a specific resource from the thread's resources.
+ * This is called outside of a mutex, so have to be aware about external
+ * changes to the structure as we read it.
+ */
+ TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
}
thread_id = tsrm_thread_id();
} else {
} while (thread_resources);
}
tsrm_mutex_unlock(tsmm_mutex);
- return ts_resource_read( thread_resources, id );
-}
-
-
-/* Read a specific resource from the thread's resources.
- * This is called outside of a mutex, so have to be aware about external
- * changes to the structure as we read it.
- */
-void *ts_resource_read( tsrm_tls_entry *thread_resources, ts_rsrc_id id )
-{
- void *resource;
-
- resource = TSRM_SAFE_ARRAY_OFFSET(thread_resources->storage, TSRM_UNSHUFFLE_RSRC_ID(id), thread_resources->count);
- if (resource) {
- TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Successfully fetched resource id %d for thread id %ld - %x", id, (long) thread_resources->thread_id, (long) resource));
- } else {
- TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Resource id %d is out of range (%d..%d)", id, TSRM_SHUFFLE_RSRC_ID(0), TSRM_SHUFFLE_RSRC_ID(thread_resources->count-1)));
- abort();
- }
- return resource;
+ /* Read a specific resource from the thread's resources.
+ * This is called outside of a mutex, so have to be aware about external
+ * changes to the structure as we read it.
+ */
+ TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
}
if (thread_resources->thread_id == thread_id) {
for (i=0; i<thread_resources->count; i++) {
if (resource_types_table[i].dtor) {
- resource_types_table[i].dtor(thread_resources->storage[i]);
+ resource_types_table[i].dtor(thread_resources->storage[i], &thread_resources->storage);
}
}
for (i=0; i<thread_resources->count; i++) {
# define MUTEX_T st_mutex_t
#endif
-typedef void (*ts_allocate_ctor)(void *);
-typedef void (*ts_allocate_dtor)(void *);
+typedef void (*ts_allocate_ctor)(void *, void ***);
+typedef void (*ts_allocate_dtor)(void *, void ***);
#define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
TSRM_API void tsrm_shutdown(void);
/* allocates a new thread-safe-resource id */
-TSRM_API ts_rsrc_id ts_allocate_id(size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
+TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
/* fetches the requested resource for the current thread */
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id);
TSRM_API void *tsrm_set_new_thread_begin_handler(void (*new_thread_begin_handler)(THREAD_T thread_id));
TSRM_API void *tsrm_set_new_thread_end_handler(void (*new_thread_end_handler)(THREAD_T thread_id));
+#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
+#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
+
+#define TSRMLS_FETCH() void ***tsrm_ls = ts_resource_ex(0, NULL)
+#define TSRMG(id, type, element) (((type) (*tsrm_ls)[TSRM_UNSHUFFLE_RSRC_ID(id)])->element)
+#define TSRMLS_D void ***tsrm_ls
+#define TSRMLS_DC , TSRMLS_D
+#define TSRMLS_C tsrm_ls
+#define TSRMLS_CC , TSRMLS_C
+
#ifdef __cplusplus
}
#endif