You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Aaron Bannert <aa...@clove.org> on 2002/08/03 19:51:55 UTC

[PATCH] new Resource List interface for apr-util

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
 * <http://www.apache.org/>.
 */

#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 */

Re: [PATCH] new Resource List interface for apr-util

Posted by Aaron Bannert <aa...@clove.org>.
On Sat, Aug 03, 2002 at 12:57:12PM -0700, Pier Fumagalli wrote:
> It looks great... The only "nitpick" I might have to make (forgot to tell
> you earlier) is that instead of apr_reslist_get and apr_reslist_put, those
> should be called apr_reslist_acquire and apr_reslist_release, like in locks,
> because this is what we do (we acquire a resource, locking it intrinsically,
> and release it after we're done with it).
> 
> Get and put (especially put) seems to imply that I can create a resource,
> and put it in the list, while we want to use the constructor and destructor
> functions... :)

Sounds totally reasonable to me, I'll do the rename and commit it to
CVS tonight.

-aaron

Re: [PATCH] new Resource List interface for apr-util

Posted by Pier Fumagalli <pi...@betaversion.org>.
It looks great... The only "nitpick" I might have to make (forgot to tell
you earlier) is that instead of apr_reslist_get and apr_reslist_put, those
should be called apr_reslist_acquire and apr_reslist_release, like in locks,
because this is what we do (we acquire a resource, locking it intrinsically,
and release it after we're done with it).

Get and put (especially put) seems to imply that I can create a resource,
and put it in the list, while we want to use the constructor and destructor
functions... :)

    Pier

"Aaron Bannert" <aa...@clove.org> wrote:

> 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
> * <http://www.apache.org/>.
> */
> 
> #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 */
> 
>