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

timer_destroy.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: timer_destroy.c,v 1.2 2005/09/15 18:14:11 klmitch Exp $
00019 */
00027 #include "engines_int.h"
00028 
00029 RCSTAG("@(#)$Id: timer_destroy.c,v 1.2 2005/09/15 18:14:11 klmitch Exp $");
00030 
00031 ev_err_t
00032 _timer_untree(ev_ctx_t *ctx, ev_tim_t *tim)
00033 {
00034   ev_tim_t *end;
00035   ev_err_t err = 0;
00036 
00037   ev_trace();
00038 
00039   ev_assert(ctx->ec_timtree.tt_root);
00040 
00041   /* Check to see if this is the last timer in the tree */
00042   if (!ctx->ec_timtree.tt_root->ti_node.tn_left) {
00043     ev_assert(ctx->ec_timtree.tt_root == tim);
00044 
00045     /* empty the tree */
00046     ctx->ec_timtree.tt_root = 0;
00047     ctx->ec_timtree.tt_insert = 0;
00048 
00049     /* Clear the node pointers */
00050     tt_node_init(tim, 0, 0);
00051 
00052     ev_return(0); /* short-circuit the rest of the checks */
00053   }
00054 
00055   ev_assert(ctx->ec_timtree.tt_insert);
00056 
00057   /* Find the end node of the tree... */
00058   if (ctx->ec_timtree.tt_insert->ti_node.tn_right) {
00059     /* cursor points to a full node; grab the right child... */
00060     end = ctx->ec_timtree.tt_insert->ti_node.tn_right;
00061     ctx->ec_timtree.tt_insert->ti_node.tn_right = 0;
00062   } else { /* cursor points to a half-full node... */
00063     end = ctx->ec_timtree.tt_insert->ti_node.tn_left; /* take left child */
00064     ctx->ec_timtree.tt_insert->ti_node.tn_left = 0;
00065 
00066     /* Move the cursor back to point at a full node if there is one... */
00067     ctx->ec_timtree.tt_insert =
00068       (ctx->ec_timtree.tt_insert->ti_node.tn_prev == ctx->ec_timtree.tt_root &&
00069        !ctx->ec_timtree.tt_root->ti_node.tn_left) ?
00070       0 : ctx->ec_timtree.tt_insert->ti_node.tn_prev;
00071   }
00072 
00073   ev_assert(end->ti_node.tn_prev);
00074   ev_assert(!end->ti_node.tn_next);
00075 
00076   /* unlink end node from the linked list threading through the tree */
00077   end->ti_node.tn_prev->ti_node.tn_next = 0;
00078 
00079   if (end != tim) { /* substitute end node for timer */
00080     int tmp;
00081 
00082     end->ti_node = tim->ti_node; /* move node pointers over */
00083     tt_node_fix(end); /* fix most of the referring pointers */
00084 
00085     if (!end->ti_node.tn_parent) /* no parent means this is the root... */
00086       ctx->ec_timtree.tt_root = end;
00087     else if (end->ti_node.tn_parent->ti_node.tn_left == tim)
00088       /* parent pointed from the left; update that pointer */
00089       end->ti_node.tn_parent->ti_node.tn_left = end;
00090     else /* parent pointed from the right; update that pointer */
00091       end->ti_node.tn_parent->ti_node.tn_right = end;
00092 
00093     if (ctx->ec_timtree.tt_insert == tim) /* fix insertion cursor */
00094       ctx->ec_timtree.tt_insert = end;
00095 
00096     if ((tmp = tv_comp(&end->ti_expire, &tim->ti_expire)) < 0)
00097       /* new value is earlier than the old timer */
00098       err = _timer_heapify_down(ctx, end);
00099     else if (tmp > 0) /* new value is later than the old timer */
00100       err = _timer_heapify_up(ctx, end);
00101   }
00102 
00103   tt_node_init(tim, 0, 0); /* clear the node */
00104 
00105   ev_return(err);
00106 }
00107 
00108 ev_err_t
00109 timer_destroy(ev_ctx_t *ctx, ev_tim_t *tim)
00110 {
00111   ev_engine_t *eng;
00112   ev_err_t err, err2;
00113 
00114   ev_init(); /* make sure library is initialized... */
00115 
00116   /* sanity-check the arguments... */
00117   if (!ec_verify(ctx) || !ti_verify(tim) || eg_context(tim) != ctx)
00118     ev_return(EINVAL);
00119 
00120   if (eg_flags(tim) & EV_GEN_DELETED) /* skip already deleted timers */
00121     ev_return(0);
00122 
00123   err = _timer_untree(ctx, tim); /* remove timer from timer tree... */
00124 
00125   /* Walk through all the timer engines (last to first)... */
00126   for (eng = ctx->ec_timer.el_last; eng;
00127        eng = eng->eng_timer.eti_active.el_prev)
00128     if ((err2 = eng_tim_rem(ctx, eng, tim)) && !err) /* remove the timer... */
00129       err = err2; /* don't interrupt removal, but remember error code */
00130 
00131   eg_flags_set(tim, EV_GEN_DELETED); /* mark it as deleted */
00132 
00133   /* decrement the reference count */
00134   eg_ref_dec(ctx, tim);
00135 
00136   ev_return(err);
00137 }

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