ply_list_t *fd_watches;
uint32_t is_getting_polled : 1;
uint32_t is_disconnected : 1;
+ int reference_count;
} ply_event_source_t;
typedef struct
free (watch);
}
+static void
+ply_event_source_take_reference (ply_event_source_t *source)
+{
+ source->reference_count++;
+}
+
static ply_event_source_t *
ply_event_source_new (int fd)
{
source->fd_watches = ply_list_new ();
source->is_getting_polled = false;
source->is_disconnected = false;
+ source->reference_count = 0;
return source;
}
free (source);
}
+static void
+ply_event_source_drop_reference (ply_event_source_t *source)
+{
+ if (source == NULL)
+ return;
+
+ source->reference_count--;
+
+ assert (source->reference_count >= 0);
+
+ if (source->reference_count == 0)
+ {
+ ply_event_source_free (source);
+ }
+}
+
static void
ply_event_loop_update_source_event_mask (ply_event_loop_t *loop,
ply_event_source_t *source)
assert (source != NULL);
destination->source = source;
+ ply_event_source_take_reference (source);
destination_node = ply_list_append_data (source->destinations, destination);
assert (destination_node != NULL);
assert (destination->source == source);
watch = ply_fd_watch_new (destination);
+ ply_event_source_take_reference (source);
ply_list_append_data (source->fd_watches, watch);
return watch;
assert (source != NULL);
ply_list_remove_data (source->destinations, destination);
+ ply_event_source_drop_reference (source);
assert (ply_list_find_node (source->destinations, destination) == NULL);
ply_event_loop_update_source_event_mask (loop, source);
}
source->is_getting_polled = true;
+ ply_event_source_take_reference (source);
ply_list_append_data (loop->sources, source);
}
}
ply_list_remove_node (loop->sources, source_node);
+ ply_event_source_drop_reference (source);
}
static void
{
ply_trace ("source for fd %d is already disconnected", source->fd);
ply_list_remove_data (source->fd_watches, watch);
+ ply_event_source_drop_reference (source);
ply_fd_watch_free (watch);
return;
}
ply_event_loop_remove_destination_by_fd_watch (loop, watch);
ply_list_remove_data (source->fd_watches, watch);
+ ply_event_source_drop_reference (source);
ply_fd_watch_free (watch);
ply_event_destination_free (destination);
{
ply_trace ("no more destinations remaing for fd %d, removing source", source->fd);
ply_event_loop_remove_source (loop, source);
- ply_trace ("freeing source for fd %d", source->fd);
- ply_event_source_free (source);
}
}
assert (watch != NULL);
ply_fd_watch_free (watch);
ply_list_remove_node (source->fd_watches, node);
+ ply_event_source_drop_reference (source);
node = next_node;
}
}
ply_event_destination_free (destination);
ply_list_remove_node (source->destinations, node);
+ ply_event_source_drop_reference (source);
node = next_node;
}
}
ply_trace ("removing source with fd %d from event loop", source->fd);
ply_event_loop_remove_source (loop, source);
ply_trace ("done removing source with fd %d from event loop", source->fd);
-
- ply_trace ("freeing source with fd %d", source->fd);
- ply_event_source_free (source);
}
static void
}
while ((number_of_received_events < 0) && ((errno == EINTR) || (errno == EAGAIN)));
+ /* first reference all sources, so they stay alive for the duration of this
+ * iteration of the loop
+ */
+ for (i = 0; i < number_of_received_events; i++)
+ {
+ ply_event_source_t *source;
+ source = (ply_event_source_t *) (events[i].data.ptr);
+
+ ply_event_source_take_reference (source);
+ }
+
+ /* Then process the incoming events
+ */
for (i = 0; i < number_of_received_events; i++)
{
ply_event_source_t *source;
if (loop->should_exit)
break;
}
+
+ /* Finally, kill off any unused sources
+ */
+ for (i = 0; i < number_of_received_events; i++)
+ {
+ ply_event_source_t *source;
+
+ source = (ply_event_source_t *) (events[i].data.ptr);
+
+ ply_event_source_drop_reference (source);
+ }
}
void