Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

event_gen_register.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 2005 by Kevin L. Mitchell <klmitch@mit.edu>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 **
00018 ** @(#)$Id: event_gen_register.c,v 1.7 2005/12/18 00:15:11 klmitch Exp $
00019 */
00027 #include "event_int.h"
00028 
00029 #include <stdlib.h>
00030 #include <string.h>
00031 
00032 RCSTAG("@(#)$Id: event_gen_register.c,v 1.7 2005/12/18 00:15:11 klmitch Exp $");
00033 
00040 struct generator {
00041   unsigned int  gentype;        
00042   ev_magic_t    genmagic;       
00043   size_t        gensize;        
00044   ev_freegen_t  genrel;         
00046 };
00047 
00060 #define gd_init(gd, desc)                                                     \
00061 do {                                                                          \
00062   ev_gendesc_t *_gd = (gd);                                                   \
00063   struct generator *_desc = (desc);                                           \
00064   /* initialize generator descriptor */                                       \
00065   _gd->gd_type = _desc->gentype; /* remember type... */                       \
00066   _gd->gd_magic = _desc->genmagic; /* ...magic number... */                   \
00067   _gd->gd_size = _desc->gensize; /* ...generator size... */                   \
00068   _gd->gd_release = _desc->genrel; /* ...and generator release callback */    \
00069   /* zero the generator lists... */                                           \
00070   _gd->gd_active.gl_count = 0;                                                \
00071   _gd->gd_active.gl_list = 0;                                                 \
00072   _gd->gd_free.gl_count = 0;                                                  \
00073   _gd->gd_free.gl_list = 0;                                                   \
00074 } while (0)
00075 
00088 #define gens_link(ctx, gens)                                                  \
00089 do {                                                                          \
00090   ev_ctx_t *_ctx = (ctx);                                                     \
00091   ev_gens_t *_gens = (gens);                                                  \
00092   if (_gens->gs_next) /* update next element's prev pointer */                \
00093     _gens->gs_next->gs_prev = _gens;                                          \
00094   if (_gens->gs_prev) /* update previous element's next pointer */            \
00095     _gens->gs_prev->gs_next = _gens;                                          \
00096   else /* oops, first entry... */                                             \
00097     _ctx->ec_gens = _gens;                                                    \
00098 } while (0)
00099 
00118 static ev_err_t
00119 gens_construct(ev_ctx_t *ctx, ev_gens_t *prev, ev_gens_t *next,
00120                struct generator *desc)
00121 {
00122   ev_gens_t *gens;
00123 
00124   ev_trace();
00125 
00126   /* allocate the thing... */
00127   if (!(gens = (ev_gens_t *)malloc(sizeof(ev_gens_t))))
00128     ev_return(ENOMEM);
00129 
00130   /* Now initialize it... */
00131   gens->gs_next = next; /* initialize list pointers... */
00132   gens->gs_prev = prev;
00133 
00134   gens->gs_first = desc->gentype; /* remember type... */
00135   gens->gs_count = 1; /* only one generator here... */
00136 
00137   /* initialize generator descriptor */
00138   gd_init(&gens->gs_gens[0], desc);
00139 
00140   if (desc->gentype > ctx->ec_maxgen) /* keep track of largest generator */
00141     ctx->ec_maxgen = desc->gentype;
00142 
00143   /* finally, link it into the right place... */
00144   gens_link(ctx, gens);
00145 
00146   ev_return(0); /* all done! */
00147 }
00148 
00166 static ev_err_t
00167 gens_extend(ev_ctx_t *ctx, ev_gens_t *gens, struct generator *desc)
00168 {
00169   ev_gendesc_t *gd;
00170 
00171   ev_trace();
00172 
00173   ev_assert(gens); /* should never be NULL here... */
00174 
00175   /* resize the gens... */
00176   if (!(gens = (ev_gens_t *)realloc(gens, sizeof(ev_gens_t) +
00177                                     sizeof(ev_gendesc_t) * gens->gs_count)))
00178     ev_return(ENOMEM);
00179 
00180   if (gens->gs_first > desc->gentype) { /* expanding at the beginning */
00181     memmove(&gens->gs_gens[1], &gens->gs_gens[0], /* shift the array over */
00182             sizeof(ev_gendesc_t) * gens->gs_count);
00183     gens->gs_first = desc->gentype; /* shift the first type... */
00184     gd = &gens->gs_gens[0]; /* put new generator at beginning */
00185   } else
00186     gd = &gens->gs_gens[gens->gs_count]; /* put new generator at end */
00187 
00188   gens->gs_count++; /* increment the count of generators... */
00189 
00190   /* initialize generator descriptor */
00191   gd_init(gd, desc);
00192 
00193   if (desc->gentype > ctx->ec_maxgen) /* keep track of largest generator */
00194     ctx->ec_maxgen = desc->gentype;
00195 
00196   /* finally, clean up links... */
00197   gens_link(ctx, gens);
00198 
00199   ev_return(0); /* all done! */
00200 }
00201 
00223 static ev_err_t
00224 gens_merge(ev_ctx_t *ctx, ev_gens_t *gens, struct generator *desc)
00225 {
00226   ev_gens_t *new;
00227 
00228   ev_trace();
00229 
00230   ev_assert(gens); /* there must be an entry... */
00231   ev_assert(gens->gs_next); /* ...and a next entry */
00232 
00233   /* allocate new gens structure... */
00234   if (!(new = (ev_gens_t *)malloc(sizeof(ev_gens_t) + sizeof(ev_gendesc_t) *
00235                                   (gens->gs_count + gens->gs_next->gs_count))))
00236     ev_return(ENOMEM);
00237 
00238   /* initialize it... */
00239   new->gs_next = gens->gs_next->gs_next; /* taking out *two* entries */
00240   new->gs_prev = gens->gs_prev;
00241 
00242   new->gs_first = gens->gs_first; /* remember first type... */
00243   new->gs_count = gens->gs_count + gens->gs_next->gs_count + 1; /* and count */
00244 
00245   /* now copy old gendescs... */
00246   memcpy(&new->gs_gens[0], &gens->gs_gens[0], /* copy first entry... */
00247          sizeof(ev_gendesc_t) * gens->gs_count);
00248 
00249   /* and the last entry... */
00250   memcpy(&new->gs_gens[gens->gs_count + 1], &gens->gs_next->gs_gens[0],
00251          sizeof(ev_gendesc_t) * gens->gs_next->gs_count);
00252 
00253   /* next, initialize the newly allocated gendesc */
00254   gd_init(&new->gs_gens[gens->gs_count], desc);
00255 
00256   /* This should never be the maximum generator... */
00257   ev_assert(desc->gentype <= ctx->ec_maxgen);
00258 
00259   /* Link it into the right place... */
00260   gens_link(ctx, new);
00261 
00262   /* and release the memory for the old ones. */
00263   free(gens->gs_next); /* free the second one first... */
00264   free(gens); /* so that we don't reference freed memory */
00265 
00266   ev_return(0); /* all done! */
00267 }
00268 
00269 ev_err_t
00270 event_gen_register(ev_ctx_t *ctx, unsigned int gentype, ev_magic_t genmagic,
00271                    size_t gensize, ev_freegen_t genrel)
00272 {
00273   ev_gens_t *gens, *last = 0;
00274   struct generator desc;
00275 
00276   ev_init(); /* make sure library is initialized... */
00277 
00278   if (!ec_verify(ctx) || gentype == EGT_NONE || !genmagic ||
00279       gensize < sizeof(ev_genhdr_t))
00280     ev_return(EINVAL); /* sanity-check arguments */
00281 
00282   desc.gentype = gentype; /* initialize the generator description */
00283   desc.genmagic = genmagic;
00284   desc.gensize = gensize;
00285   desc.genrel = genrel;
00286 
00287   /* if no entries or if the gentype is at the beginning of the list... */
00288   if (!ctx->ec_gens || gentype < ctx->ec_gens->gs_first - 1)
00289     /* just construct the thing... */
00290     ev_return(gens_construct(ctx, 0, ctx->ec_gens, &desc));
00291 
00292   /* walk through the list and find a place to insert generator */
00293   for (gens = ctx->ec_gens; gens; last = gens, gens = gens->gs_next) {
00294     /* duplicate generator? */
00295     if (gentype >= gens->gs_first && gentype < gens->gs_first + gens->gs_count)
00296       ev_return(EV_ERR_DUPGEN);
00297 
00298     /* Have we found an insertion point? */
00299     if (gentype >= gens->gs_first + gens->gs_count && gens->gs_next &&
00300         gentype < gens->gs_next->gs_first)
00301       break; /* all done! */
00302   }
00303 
00304   ev_assert(gens || last); /* one of these must be non-zero */
00305 
00306   /* inserting at end of list... */
00307   if (!gens && gentype != last->gs_first + last->gs_count)
00308     ev_return(gens_construct(ctx, last, 0, &desc));
00309   else if (!gens) /* OK, we're extending the last entry... */
00310     gens = last;
00311 
00312   /* OK, insertion point is somewhere in the middle... */
00313   if (gentype == gens->gs_first + gens->gs_count ||
00314       (gens->gs_next && gentype == gens->gs_next->gs_first - 1)) {
00315     /* extending or merging...but which? */
00316     if (gentype == gens->gs_first + gens->gs_count &&
00317         gens->gs_next && gentype == gens->gs_next->gs_first - 1)
00318       ev_return(gens_merge(ctx, gens, &desc)); /* merging! */
00319 
00320     /* OK, extending... */
00321     ev_return(gens_extend(ctx, ((gentype == gens->gs_first + gens->gs_count) ?
00322                                 gens : gens->gs_next), &desc));
00323   }
00324 
00325   /* OK, construct a new entry */
00326   ev_return(gens_construct(ctx, gens, gens->gs_next, &desc));
00327 }

Generated on Wed Dec 28 23:36:56 2005 for event by  doxygen 1.4.4