Annotation of embedaddon/libpdel/util/tinfo.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (c) 2001-2002 Packet Design, LLC.
! 4: * All rights reserved.
! 5: *
! 6: * Subject to the following obligations and disclaimer of warranty,
! 7: * use and redistribution of this software, in source or object code
! 8: * forms, with or without modifications are expressly permitted by
! 9: * Packet Design; provided, however, that:
! 10: *
! 11: * (i) Any and all reproductions of the source or object code
! 12: * must include the copyright notice above and the following
! 13: * disclaimer of warranties; and
! 14: * (ii) No rights are granted, in any manner or form, to use
! 15: * Packet Design trademarks, including the mark "PACKET DESIGN"
! 16: * on advertising, endorsements, or otherwise except as such
! 17: * appears in the above copyright notice or in the software.
! 18: *
! 19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 36: * THE POSSIBILITY OF SUCH DAMAGE.
! 37: *
! 38: * Author: Archie Cobbs <archie@freebsd.org>
! 39: */
! 40:
! 41: #include <sys/types.h>
! 42:
! 43: #include <stdio.h>
! 44: #include <stdarg.h>
! 45: #include <string.h>
! 46: #include <pthread.h>
! 47: #include <errno.h>
! 48:
! 49: #include "structs/structs.h"
! 50: #include "structs/type/array.h"
! 51: #include "util/typed_mem.h"
! 52: #include "util/tinfo.h"
! 53:
! 54: /* Per-thread tinfo data */
! 55: struct tinfo_private {
! 56: struct tinfo *t;
! 57: void *data; /* user data */
! 58: };
! 59:
! 60: /* Internal variables */
! 61: static struct tinfo_private *tinfo_init(struct tinfo *t);
! 62: static void tinfo_instance_destroy(void *arg);
! 63:
! 64: /*
! 65: * Get the per-thread instance, creating a new one if none there.
! 66: *
! 67: * Note: the returned value should NOT be free'd by the caller.
! 68: */
! 69: void *
! 70: tinfo_get(struct tinfo *t)
! 71: {
! 72: struct tinfo_private *priv;
! 73:
! 74: /* Get instance container */
! 75: if ((priv = tinfo_init(t)) == NULL)
! 76: return (NULL);
! 77:
! 78: /* Has instance been constructed yet? If not, construct one */
! 79: if (priv->data == NULL) {
! 80:
! 81: /* Create a new instance for this thread */
! 82: if ((priv->data = MALLOC(t->mtype, t->type->size)) == NULL)
! 83: return (NULL);
! 84:
! 85: /* Run application initializer (if any) or else default */
! 86: if ((t->init != NULL ? (*t->init)(t, priv->data) :
! 87: structs_init(t->type, NULL, priv->data)) == -1) {
! 88: FREE(t->mtype, priv->data);
! 89: priv->data = NULL;
! 90: }
! 91: }
! 92:
! 93: /* Done */
! 94: return (priv->data);
! 95: }
! 96:
! 97: /*
! 98: * Set a new value for the per-thread variable.
! 99: */
! 100: int
! 101: tinfo_set(struct tinfo *t, const void *data)
! 102: {
! 103: struct tinfo_private *priv;
! 104: void *copy;
! 105:
! 106: /* Get instance container */
! 107: if ((priv = tinfo_init(t)) == NULL)
! 108: return (-1);
! 109:
! 110: /* Handle case where data is NULL */
! 111: if (data == NULL) {
! 112: if (priv->data != NULL) {
! 113: structs_free(t->type, NULL, priv->data);
! 114: FREE(t->mtype, priv->data);
! 115: priv->data = NULL;
! 116: }
! 117: return (0);
! 118: }
! 119:
! 120: /* Copy new data provided by caller */
! 121: if ((copy = MALLOC(t->mtype, t->type->size)) == NULL)
! 122: return (-1);
! 123: if (structs_get(t->type, NULL, data, copy) == -1) {
! 124: FREE(t->mtype, copy);
! 125: return (-1);
! 126: }
! 127:
! 128: /* Set copy */
! 129: if (tinfo_set_nocopy(t, copy) == -1) {
! 130: structs_free(t->type, NULL, priv->data);
! 131: FREE(t->mtype, copy);
! 132: }
! 133:
! 134: /* Done */
! 135: return (0);
! 136: }
! 137:
! 138: /*
! 139: * Set a new value for the per-thread variable without copying.
! 140: */
! 141: int
! 142: tinfo_set_nocopy(struct tinfo *t, void *data)
! 143: {
! 144: struct tinfo_private *priv;
! 145:
! 146: /* Get instance container */
! 147: if ((priv = tinfo_init(t)) == NULL)
! 148: return (-1);
! 149:
! 150: /* Free existing value, if any */
! 151: if (priv->data != NULL) {
! 152: structs_free(t->type, NULL, priv->data);
! 153: FREE(t->mtype, priv->data);
! 154: }
! 155:
! 156: /* Set new value */
! 157: priv->data = data;
! 158: return (0);
! 159: }
! 160:
! 161: /*
! 162: * Initialize per-thread variable if not already initialized.
! 163: */
! 164: static struct tinfo_private *
! 165: tinfo_init(struct tinfo *t)
! 166: {
! 167: struct tinfo_private *priv;
! 168:
! 169: /* Initialize key, once for all threads */
! 170: if (t->pkey == TINFO_KEY_INIT
! 171: && (errno = pthread_key_create(&t->pkey,
! 172: tinfo_instance_destroy)) != 0) {
! 173: t->pkey = TINFO_KEY_INIT;
! 174: return (NULL);
! 175: }
! 176:
! 177: /* Construct instance container for this thread if needed */
! 178: if ((priv = pthread_getspecific(t->pkey)) == NULL) {
! 179:
! 180: /* Get new instance container (a struct tinfo_private) */
! 181: if ((priv = MALLOC(t->mtype, sizeof(*priv))) == NULL)
! 182: return (NULL);
! 183: memset(priv, 0, sizeof(*priv));
! 184: priv->t = t;
! 185:
! 186: /* Store the container as the per-thread variable */
! 187: if ((errno = pthread_setspecific(t->pkey, priv)) != 0) {
! 188: FREE(t->mtype, priv);
! 189: return (NULL);
! 190: }
! 191: }
! 192:
! 193: /* Done */
! 194: return (priv);
! 195: }
! 196:
! 197: /*
! 198: * Destructor called upon thread exit.
! 199: */
! 200: static void
! 201: tinfo_instance_destroy(void *arg)
! 202: {
! 203: struct tinfo_private *const priv = arg;
! 204: struct tinfo *const t = priv->t;
! 205:
! 206: /* Free instance */
! 207: if (priv->data != NULL) {
! 208: structs_free(t->type, NULL, priv->data);
! 209: FREE(t->mtype, priv->data);
! 210: }
! 211:
! 212: /* Free container */
! 213: FREE(t->mtype, priv);
! 214: }
! 215:
! 216:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>