Definitelly fix ticket #127. Iterators now support asynchronous remove.

This commit is contained in:
Vreixo Formoso 2008-03-08 00:45:19 +01:00
parent 620c7a08e1
commit ae43626f0b
3 changed files with 65 additions and 39 deletions

View File

@ -93,13 +93,20 @@ int find_iter_remove(IsoDirIter *iter)
return iso_dir_iter_remove(data->iter);
}
void find_notify_child_taken(IsoDirIter *iter, IsoNode *node)
{
/* nothing to do */
return;
}
static
struct iso_dir_iter_iface find_iter_class = {
find_iter_next,
find_iter_has_next,
find_iter_free,
find_iter_take,
find_iter_remove
find_iter_remove,
find_notify_child_taken
};
int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond,

View File

@ -485,6 +485,10 @@ int iso_node_take(IsoNode *node)
/* should never occur */
return ISO_ASSERT_FAILURE;
}
/* notify iterators just before remove */
iso_notify_dir_iters(node, 0);
*pos = node->next;
node->parent = NULL;
node->next = NULL;
@ -531,7 +535,6 @@ static
int iter_take(IsoDirIter *iter)
{
struct dir_iter_data *data;
IsoNode *pos, *pre;
if (iter == NULL) {
return ISO_NULL_POINTER;
}
@ -549,38 +552,7 @@ int iter_take(IsoDirIter *iter)
/* clear next flag */
data->flag &= ~0x01;
pos = iter->dir->children;
pre = NULL;
while (pos != NULL && pos != data->pos) {
pre = pos;
pos = pos->next;
}
if (pos == NULL) {
return ISO_ERROR; /* node not in dir */
}
if (pos != data->pos) {
return ISO_ASSERT_FAILURE;
}
/* dispose iterator reference */
iso_node_unref(data->pos);
if (pre == NULL) {
/* node is a first position */
iter->dir->children = pos->next;
data->pos = NULL;
} else {
pre->next = pos->next;
data->pos = pre;
iso_node_ref(pre); /* take iter ref */
}
/* take pos */
pos->parent = NULL;
pos->next = NULL;
iter->dir->nchildren--;
return ISO_SUCCESS;
return iso_node_take(data->pos);
}
static
@ -601,19 +573,49 @@ int iter_remove(IsoDirIter *iter)
/* remove node */
iso_node_unref(pos);
}
if (data->pos == pos) {
return ISO_ERROR;
}
return ret;
}
void iter_notify_child_taken(IsoDirIter *iter, IsoNode *node)
{
IsoNode *pos, *pre;
struct dir_iter_data *data;
data = iter->data;
if (data->pos == node) {
pos = iter->dir->children;
pre = NULL;
while (pos != NULL && pos != data->pos) {
pre = pos;
pos = pos->next;
}
if (pos == NULL || pos != data->pos) {
return;
}
/* dispose iterator reference */
iso_node_unref(data->pos);
if (pre == NULL) {
/* node is a first position */
iter->dir->children = pos->next;
data->pos = NULL;
} else {
pre->next = pos->next;
data->pos = pre;
iso_node_ref(pre); /* take iter ref */
}
}
}
static
struct iso_dir_iter_iface iter_class = {
iter_next,
iter_has_next,
iter_free,
iter_take,
iter_remove
iter_remove,
iter_notify_child_taken
};
int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter)
@ -1021,6 +1023,18 @@ void iso_dir_iter_unregister(IsoDirIter *iter)
}
}
void iso_notify_dir_iters(IsoNode *node, int flag)
{
struct iter_reg_node *pos = iter_reg;
while (pos != NULL) {
IsoDirIter *iter = pos->iter;
if (iter->dir == node->parent) {
iter->class->notify_child_taken(iter, node);
}
pos = pos->next;
}
}
int iso_node_new_root(IsoDir **root)
{
IsoDir *dir;

View File

@ -161,6 +161,11 @@ struct iso_dir_iter_iface
int (*remove)(IsoDirIter *iter);
/**
* This is called just before remove a node from a directory. The iterator
* may want to update its internal state according to this.
*/
void (*notify_child_taken)(IsoDirIter *iter, IsoNode *node);
};
/**
@ -334,6 +339,6 @@ int iso_dir_iter_register(IsoDirIter *iter);
*/
void iso_dir_iter_unregister(IsoDirIter *iter);
void iso_notify_dir_iters(IsoNode *node, int flag);
#endif /*LIBISO_NODE_H_*/