or <<mainloop:fun_main_destroy,`main_destroy()`>> to clean up properly after fork().
** Added support for <<mainloop:signal,synchronous delivery of signals>>.
** Added relative timers: <<mainloop:fun_timer_add_rel,`timer_add_rel()`>>.
-** Modification of events from a running event handler should be always safe.
+** Modification of events from a running event handler is always safe.
+** Deleting an already deleted event is always safe.
** For any event type, it is possible to ask whether it is active (added to the mainloop) or not: <<mainloop:fun_hook_is_active,`hook_is_active()`>> and friends.
** A new mainloop front-end for asynchronous <<mainloop:recordio,record-based I/O>> has been added.
/*
* UCW Library -- Main Loop: Record I/O
*
- * (c) 2011 Martin Mares <mj@ucw.cz>
+ * (c) 2011--2012 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
void
rec_io_del(struct main_rec_io *rio)
{
+ if (!rec_io_is_active(rio))
+ return;
+
timer_del(&rio->timer);
- if (hook_is_active(&rio->start_read_hook))
- hook_del(&rio->start_read_hook);
+ hook_del(&rio->start_read_hook);
file_del(&rio->file);
if (rio->read_buf)
/*
* UCW Library -- Main Loop
*
- * (c) 2004--2011 Martin Mares <mj@ucw.cz>
+ * (c) 2004--2012 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
// XXX: Can be called on a non-current context
DBG("MAIN: Deleting file %p (fd=%d)", fi, fi->fd);
- ASSERT(file_is_active(fi));
+ if (!file_is_active(fi))
+ return;
clist_unlink(&fi->n);
m->file_cnt--;
#ifdef CONFIG_UCW_EPOLL
struct main_context *m = main_current();
DBG("MAIN: Adding hook %p", ho);
- ASSERT(!hook_is_active(ho));
- clist_add_tail(&m->hook_list, &ho->n);
+ if (!hook_is_active(ho))
+ clist_add_tail(&m->hook_list, &ho->n);
}
void
hook_del(struct main_hook *ho)
{
DBG("MAIN: Deleting hook %p", ho);
- ASSERT(hook_is_active(ho));
- clist_unlink(&ho->n);
+ if (hook_is_active(ho))
+ clist_unlink(&ho->n);
}
static void
process_del(struct main_process *mp)
{
DBG("MAIN: Deleting process %p (pid=%d)", mp, mp->pid);
- ASSERT(process_is_active(mp));
- clist_unlink(&mp->n);
+ if (process_is_active(mp))
+ clist_unlink(&mp->n);
}
int
// XXX: Can be called on a non-current context
DBG("MAIN: Deleting signal %p (sig=%d)", ms, ms->signum);
- ASSERT(signal_is_active(ms));
+ if (!signal_is_active(ms))
+ return;
clist_unlink(&ms->n);
int another = 0;
/*
* UCW Library -- Main Loop
*
- * (c) 2004--2011 Martin Mares <mj@ucw.cz>
+ * (c) 2004--2012 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
/**
* Removes a timer from the active ones. It is permitted (and common) to call
* this function from the timer's handler itself if you want to deactivate
- * the timer.
+ * the timer. Removing an already removed timer does nothing.
**/
void timer_del(struct main_timer *tm);
* Inserts a new hook into the loop.
* The hook will be scheduled at least once before next sleep.
* May be called from inside a hook handler too.
+ * Adding an already added hook does nothing.
**/
void hook_add(struct main_hook *ho);
/**
* Removes an existing hook from the loop.
* May be called from inside a hook handler (to delete itself or another hook).
+ * Removing an already removed hook does nothing.
**/
void hook_del(struct main_hook *ho);
* please use this function first.
*
* Can be called from a handler.
+ * Removing an already removed file does nothing.
**/
void file_del(struct main_file *fi);
/** Activate a block I/O structure. **/
void block_io_add(struct main_block_io *bio, int fd);
-/** Deactivate a block I/O structure. **/
+/** Deactivate a block I/O structure. Calling twice is safe. **/
void block_io_del(struct main_block_io *bio);
/**
/** Activate a record I/O structure. **/
void rec_io_add(struct main_rec_io *rio, int fd);
-/** Deactivate a record I/O structure. **/
+/** Deactivate a record I/O structure. Calling twice is safe. **/
void rec_io_del(struct main_rec_io *rio);
/**
* Removes the process from the watched set. This is done
* automatically, when the process terminates, so you need it only
* when you do not want to watch a running process any more.
+ * Removing an already removed process does nothing.
*/
void process_del(struct main_process *mp);
/** Request a signal to be caught and delivered synchronously. **/
void signal_add(struct main_signal *ms);
-/** Cancel a request for signal catching. **/
+/** Cancel a request for signal catching. Calling twice is safe. **/
void signal_del(struct main_signal *ms);
/** Tells if a signal catcher is active (i.e., added). **/