pool.c (3519B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#include "config.h" 21 22#include "guacamole/mem.h" 23#include "guacamole/pool.h" 24 25#include <stdlib.h> 26 27guac_pool* guac_pool_alloc(int size) { 28 29 pthread_mutexattr_t lock_attributes; 30 guac_pool* pool = guac_mem_alloc(sizeof(guac_pool)); 31 32 /* If unable to allocate, just return NULL. */ 33 if (pool == NULL) 34 return NULL; 35 36 /* Initialize empty pool */ 37 pool->min_size = size; 38 pool->active = 0; 39 pool->__next_value = 0; 40 pool->__head = NULL; 41 pool->__tail = NULL; 42 43 /* Init lock */ 44 pthread_mutexattr_init(&lock_attributes); 45 pthread_mutexattr_setpshared(&lock_attributes, PTHREAD_PROCESS_SHARED); 46 pthread_mutex_init(&(pool->__lock), &lock_attributes); 47 48 return pool; 49 50} 51 52void guac_pool_free(guac_pool* pool) { 53 54 /* Free all ints in pool */ 55 guac_pool_int* current = pool->__head; 56 while (current != NULL) { 57 58 guac_pool_int* old = current; 59 current = current->__next; 60 61 guac_mem_free(old); 62 } 63 64 /* Destroy lock */ 65 pthread_mutex_destroy(&(pool->__lock)); 66 67 /* Free pool */ 68 guac_mem_free(pool); 69 70} 71 72int guac_pool_next_int(guac_pool* pool) { 73 74 int value; 75 76 /* Acquire exclusive access */ 77 pthread_mutex_lock(&(pool->__lock)); 78 79 pool->active++; 80 81 /* If more integers are needed, return a new one. */ 82 if (pool->__head == NULL || pool->__next_value < pool->min_size) { 83 value = pool->__next_value++; 84 pthread_mutex_unlock(&(pool->__lock)); 85 return value; 86 } 87 88 /* Otherwise, remove first integer. */ 89 value = pool->__head->value; 90 91 /* If only one element exists, reset pool to empty. */ 92 if (pool->__tail == pool->__head) { 93 guac_mem_free(pool->__head); 94 pool->__head = NULL; 95 pool->__tail = NULL; 96 } 97 98 /* Otherwise, advance head. */ 99 else { 100 guac_pool_int* old_head = pool->__head; 101 pool->__head = old_head->__next; 102 guac_mem_free(old_head); 103 } 104 105 /* Return retrieved value. */ 106 pthread_mutex_unlock(&(pool->__lock)); 107 return value; 108} 109 110void guac_pool_free_int(guac_pool* pool, int value) { 111 112 /* Allocate and initialize new returned value */ 113 guac_pool_int* pool_int = guac_mem_alloc(sizeof(guac_pool_int)); 114 pool_int->value = value; 115 pool_int->__next = NULL; 116 117 /* Acquire exclusive access */ 118 pthread_mutex_lock(&(pool->__lock)); 119 120 pool->active--; 121 122 /* If pool empty, store as sole entry. */ 123 if (pool->__tail == NULL) 124 pool->__head = pool->__tail = pool_int; 125 126 /* Otherwise, append to end of pool. */ 127 else { 128 pool->__tail->__next = pool_int; 129 pool->__tail = pool_int; 130 } 131 132 /* Value has been freed */ 133 pthread_mutex_unlock(&(pool->__lock)); 134 135} 136