Return-Path: Delivered-To: apmail-apr-dev-archive@apr.apache.org Received: (qmail 34416 invoked by uid 500); 3 Aug 2002 17:51:51 -0000 Mailing-List: contact dev-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Delivered-To: mailing list dev@apr.apache.org Received: (qmail 34405 invoked from network); 3 Aug 2002 17:51:51 -0000 Date: Sat, 3 Aug 2002 10:51:55 -0700 From: Aaron Bannert To: dev@apr.apache.org Subject: [PATCH] new Resource List interface for apr-util Message-ID: <20020803175154.GS26485@clove.org> Mail-Followup-To: Aaron Bannert , dev@apr.apache.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N Inspired by Pier and others, and motivated by the desire for a generic interface, I have created a Resource List API for threadsafe management of a group of reusable resources. It has attributes to control the minimum and maximum numbers of available resources, as well as a hard maximum on the total number and an expiration time (to prevent thrashing). Take this example: A pool of database connections (not a memory pool, which is why I went with "apr_reslist_t" :): Let's say we want to have at least 2 connections available at all times, at most 10 but to allow more than 10 if they were used within the last minute, and to never allow more than 25 total. Here's how we'd set it up: /* Creation and destruction routines for my database connections */ apr_status_t my_connection_constructor(void **my_conn, void *params, apr_pool_t *pool); apr_status_t my_connection_destructor(void *my_conn, void *params, apr_pool_t *pool); apr_reslist_create(&my_reslist, 2, 10, 25, 1*APR_USEC_PER_SEC, my_connection_constructor, my_connection_destructor, params, pool); /* Then any number of threads can do this kind of thing to use it: */ apr_reslist_get(my_reslist, (void**)&a_connection); /* Here we would do something with the connection and then later when * we're done we return it to the list like so: */ apr_reslist_put(my_reslist, a_connection); That's all there is to it (with a little handwaving in the constructor/ destructor part, but you all get the picture). Let me know what you all think, -aaron /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ #ifndef APR_RESLIST_H #define APR_RESLIST_H /** * @file apr_reslist.h * @brief APR Resource List Routines */ #include "apr.h" #include "apu.h" #include "apr_pools.h" #include "apr_errno.h" #include "apr_time.h" #if APR_HAS_THREADS /** * @defgroup APR_RMM Resource List Routines * @ingroup APR * @{ */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** Opaque resource list object */ typedef struct apr_reslist_t apr_reslist_t; /** * Generic prototypes for the constructor and destructor that * is called by the resource list any time it needs to create * or destroy a resource. */ typedef apr_status_t (*apr_reslist_constructor)(void **resource, void *params, apr_pool_t *pool); typedef apr_status_t (*apr_reslist_destructor)(void *resource, void *params, apr_pool_t *pool); /** * Create a new resource list with the following parameters: * @param reslist An address where the pointer to the new resource * list will be stored. * @param pool The pool to use for local storage and management * @param min Allowed minimum number of available resources. Zero * creates new resources only when needed. * @param smax Resources will be destroyed to meet this maximum * restriction as they expire. * @param hmaxx Absolute maximum limit on the number of total resources. * @param expire If non-zero, sets the maximum amount of time a resource * may be available while exceeding the soft limit. * @param con Constructor routine that is called to create a new resource. * @param de Destructor routine that is called to destroy an expired resource. * @param pool The pool from which to create this resoure list. Also the * same pool that is passed to the constructor and destructor * routines. */ APU_DECLARE(apr_status_t) apr_reslist_create(apr_reslist_t **reslist, int min, int smax, int hmax, apr_interval_time_t ttl, apr_reslist_constructor con, apr_reslist_destructor de, void *params, apr_pool_t *pool); /** * Destroy the given resource list and all resources controlled by * this list. * FIXME: Should this block until all resources become available, * or maybe just destroy all the free ones, or maybe destroy * them even though they might be in use by something else? * @param rmm The relocatable memory block to destroy */ APU_DECLARE(apr_status_t) apr_reslist_destroy(apr_reslist_t *reslist); /** * Retrieve a resource from the list, creating a new one if necessary. * If we have met our maximum number of resources, we will block * until one becomes available. */ APU_DECLARE(apr_status_t) apr_reslist_get(apr_reslist_t *reslist, void **resource); /** * Return a resource back to the list of available resources. */ APU_DECLARE(apr_status_t) apr_reslist_put(apr_reslist_t *reslist, void *resource); #ifdef __cplusplus } #endif /** @} */ #endif /* APR_HAS_THREADS */ #endif /* ! APR_RESLIST_H */