int errno;
+#define UPDATE_ITEM_DELETED (-1)
+#define UPDATE_INVOKED (-2)
+#define UPDATE_NOT_INVOKED (0)
+
struct item {
Ecore_Timer *timer;
struct instance *inst;
* \note
* To prevent from checking the is_updated function
*/
- (void)updator_cb(item);
+ if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
+ /* Item is destroyed */
+ }
+
if (s_info.pd_open_pending_list)
return ECORE_CALLBACK_RENEW;
* \note
* To prevent from checking the is_updated function
*/
- (void)updator_cb(item);
+ if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
+ /* item is destroyed */
+ }
+
if (s_info.pending_list)
return ECORE_CALLBACK_RENEW;
return 0;
}
-static inline void timer_thaw(struct item *item)
+/*!
+ * \brief
+ * This function can call the update callback
+ * return 0 if there is no changes
+ * return -1 the item is deleted
+ */
+static inline int timer_thaw(struct item *item)
{
double pending;
double period;
double sleep_time;
if (!item->timer)
- return;
+ return 0;
ecore_timer_thaw(item->timer);
period = ecore_timer_interval_get(item->timer);
ecore_timer_delay(item->timer, delay);
if (item->sleep_at == 0.0f)
- return;
+ return 0;
sleep_time = util_timestamp() - item->sleep_at;
- if (sleep_time > pending)
- (void)updator_cb(item);
-
item->sleep_at = 0.0f;
+
+ if (sleep_time > pending) {
+ if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
+ /* item is destroyed */
+ return UPDATE_ITEM_DELETED;
+ } else {
+ return UPDATE_INVOKED;
+ }
+ }
+
+ return UPDATE_NOT_INVOKED;
}
static inline void timer_freeze(struct item *item)
return ECORE_CALLBACK_CANCEL;
}
+/*!
+ * \note
+ * This must has to return ECORE_CALLBACK_CANCEL, only if the item is deleted.
+ * So every caller, should manage the deleted item correctly.
+ */
static Eina_Bool updator_cb(void *data)
{
struct item *item;
if (so_need_to_destroy(item->inst) == NEED_TO_DESTROY) {
provider_send_deleted(item->inst->item->pkgname, item->inst->id);
lb_destroy(item->inst->item->pkgname, item->inst->id);
+ /*!
+ * \CRITICAL
+ * Every caller of this, must not access the item from now.
+ */
return ECORE_CALLBACK_CANCEL;
}
{
char *filename;
int len;
+ int ret;
len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
filename = malloc(len);
}
snprintf(filename, len, "%s.desc", util_uri_to_path(id));
- return update_monitor_add_update_cb(filename, desc_updated_cb, item);
+ ret = update_monitor_add_update_cb(filename, desc_updated_cb, item);
+ free(filename);
+ return ret;
}
static inline int add_file_update_monitor(const char *id, struct item *item)
{
- char *filename;
-
- filename = strdup(util_uri_to_path(id));
- if (!filename) {
- ErrPrint("Heap: %s (%s)\n", strerror(errno), id);
- return LB_STATUS_ERROR_MEMORY;
- }
-
- return update_monitor_add_update_cb(filename, file_updated_cb, item);
+ return update_monitor_add_update_cb(util_uri_to_path(id), file_updated_cb, item);
}
static inline int update_monitor_add(const char *id, struct item *item)
if (!item->deleteme)
continue;
- s_info.item_list = eina_list_remove(s_info.item_list, item);
-
update_monitor_del(item->inst->id, item);
(void)so_destroy(item->inst);
free(item);
HAPI void lb_resume_all(void)
{
Eina_List *l;
+ Eina_List *n;
struct item *item;
s_info.paused = 0;
pending_timer_thaw();
- EINA_LIST_FOREACH(s_info.item_list, l, item) {
+ EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
if (item->deleteme) {
DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
continue;
if (item->is_paused)
continue;
- timer_thaw(item);
-
lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
if (item->updated_in_pause) {
(void)append_pending_list(item);
item->updated_in_pause = 0;
}
+
+ /*!
+ * \note
+ * After send the resume callback, call this function.
+ * Because the timer_thaw can call the update function.
+ * Before resumed event is notified to the livebox,
+ * Do not call update function
+ */
+ if (timer_thaw(item) == UPDATE_ITEM_DELETED) {
+ /* item is deleted */
+ }
}
}
struct instance *inst;
Eina_List *l;
struct item *item;
+ int ret;
inst = so_find_instance(pkgname, id);
if (!inst)
if (s_info.paused)
return LB_STATUS_SUCCESS;
- timer_thaw(item);
-
lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
+ ret = timer_thaw(item);
+ if (ret == UPDATE_ITEM_DELETED) {
+ /*!
+ * \note
+ * ITEM is deleted
+ */
+ return LB_STATUS_SUCCESS;
+ } else if (ret == UPDATE_INVOKED) {
+ /*!
+ * \note
+ * if the update is successfully done, the updated_in_pause will be reset'd.
+ * or append it to the pending list
+ */
+ }
+
if (item->updated_in_pause) {
(void)append_pending_list(item);
item->updated_in_pause = 0;