rts/Pool: Add poolTryTake
authorBen Gamari <ben@smart-cactus.org>
Thu, 26 Nov 2015 11:02:33 +0000 (12:02 +0100)
committerBen Gamari <ben@smart-cactus.org>
Thu, 26 Nov 2015 13:48:48 +0000 (14:48 +0100)
rts/Pool.c
rts/Pool.h

index 6c23807..b3e3446 100644 (file)
@@ -111,19 +111,40 @@ nat poolGetDesiredSize(Pool *pool) {
     return pool->desired_size;
 }
 
+// Try taking a PoolEntry with an item from a pool,
+// returning NULL if no items are available.
+static PoolEntry *poolTryTake_(Pool *pool) {
+    PoolEntry *ent = NULL;
+    if (pool->available != NULL) {
+        ent = pool->available;
+        pool->available = ent->next;
+    } else if (pool->current_size < pool->max_size) {
+        ent = stgMallocBytes(sizeof(PoolEntry), "pool_take");
+        ent->flags = 0;
+        ent->thing = pool->alloc_fn();
+        pool->current_size++;
+    } else {
+        return NULL;
+    }
+
+    ent->next = pool->taken;
+    pool->taken = ent;
+    return ent;
+}
+
+void *poolTryTake(Pool *pool) {
+    ACQUIRE_LOCK(&pool->mutex);
+    PoolEntry *ent = poolTryTake_(pool);
+    RELEASE_LOCK(&pool->mutex);
+    return ent ? ent->thing : NULL;
+}
+
 void *poolTake(Pool *pool) {
     PoolEntry *ent = NULL;
     ACQUIRE_LOCK(&pool->mutex);
     while (ent == NULL) {
-        if (pool->available != NULL) {
-            ent = pool->available;
-            pool->available = ent->next;
-        } else if (pool->current_size < pool->max_size) {
-            ent = stgMallocBytes(sizeof(PoolEntry), "pool_take");
-            ent->flags = 0;
-            ent->thing = pool->alloc_fn();
-            pool->current_size++;
-        } else {
+        ent = poolTryTake_(pool);
+        if (!ent) {
 #ifdef THREADED_RTS
             waitCondition(&pool->cond, &pool->mutex);
 #else
@@ -132,8 +153,6 @@ void *poolTake(Pool *pool) {
         }
     }
 
-    ent->next = pool->taken;
-    pool->taken = ent;
     RELEASE_LOCK(&pool->mutex);
     return ent->thing;
 }
index d1aeab5..dd00412 100644 (file)
@@ -43,7 +43,15 @@ void poolSetDesiredSize(Pool *pool, nat size);
 /* Get the desired size of a pool */
 nat poolGetDesiredSize(Pool *pool);
 
-/* Grab an available thing from a pool */
+/* Try to grab an available thing from a pool, returning NULL if no things
+ * are available.
+ */
+void *poolTryTake(Pool *pool);
+
+/* Grab an available thing from a pool. This will block if no elements are
+ * available in the case of a threaded runtime or abort in a single-threaded
+ * environment.
+ */
 void *poolTake(Pool *pool);
 
 /* Release a thing back to the pool from which it was taken */