diff --git a/src/fast_timer.c b/src/fast_timer.c index f325780ad83701da91be77bedec4947ad00b4444..e41640a9c962df9a1992ee2a3c626a27ae2f55b6 100644 --- a/src/fast_timer.c +++ b/src/fast_timer.c @@ -23,33 +23,15 @@ #include "pthread_func.h" #include "fast_timer.h" -static int fast_timer_init_locks(FastTimer *timer) +int fast_timer_init(FastTimer *timer, const int slot_count, + const int64_t current_time) { - int result; - FastTimerSlot *slot; - FastTimerSlot *end; - - end = timer->slots + timer->slot_count; - for (slot=timer->slots; slotlock)) != 0) { - return result; - } - } - - return 0; -} - -int fast_timer_init_ex(FastTimer *timer, const int slot_count, - const int64_t current_time, const bool need_lock) -{ - int result; int bytes; if (slot_count <= 0 || current_time <= 0) { return EINVAL; } - timer->need_lock = need_lock; timer->slot_count = slot_count; timer->base_time = current_time; //base time for slot 0 timer->current_time = current_time; @@ -60,84 +42,17 @@ int fast_timer_init_ex(FastTimer *timer, const int slot_count, } memset(timer->slots, 0, bytes); - if (need_lock) { - if ((result=fast_timer_init_locks(timer)) != 0) { - return result; - } - } return 0; } void fast_timer_destroy(FastTimer *timer) { if (timer->slots != NULL) { - if (timer->need_lock) { - FastTimerSlot *slot; - FastTimerSlot *end; - end = timer->slots + timer->slot_count; - for (slot=timer->slots; slotlock); - } - } - free(timer->slots); timer->slots = NULL; } } -#define TIMER_CHECK_LOCK(timer, slot) \ - do { \ - if (timer->need_lock) { \ - PTHREAD_MUTEX_LOCK(&(slot)->lock); \ - } \ - } while (0) - -#define TIMER_CHECK_UNLOCK(timer, slot) \ - do { \ - if (timer->need_lock) { \ - PTHREAD_MUTEX_UNLOCK(&(slot)->lock); \ - } \ - } while (0) - -#define TIMER_CHECK_LOCK_AND_SET_SLOT(timer, slot, entry) \ - do { \ - if (timer->need_lock) { \ - PTHREAD_MUTEX_LOCK(&(slot)->lock); \ - entry->slot_index = slot - timer->slots; \ - } \ - } while (0) - -#define TIMER_CHECK_LOCK_BY_ENTRY(timer, entry) \ - do { \ - if (timer->need_lock && entry->slot_index >= 0) { \ - PTHREAD_MUTEX_LOCK(&(timer->slots + entry->slot_index)->lock); \ - } \ - } while (0) - - -#define TIMER_CHECK_UNLOCK_AND_REMOVE_BY_ENTRY(timer, entry) \ - do { \ - if (timer->need_lock && entry->slot_index >= 0) { \ - PTHREAD_MUTEX_UNLOCK(&(timer->slots + entry->slot_index)->lock); \ - entry->slot_index = -1; \ - } \ - } while (0) - -#define TIMER_CHECK_LOCK_BY_SINDEX(timer, slot_index) \ - do { \ - if (timer->need_lock) { \ - PTHREAD_MUTEX_LOCK(&(timer->slots + slot_index)->lock); \ - } \ - } while (0) - -#define TIMER_CHECK_UNLOCK_BY_SINDEX(timer, slot_index) \ - do { \ - if (timer->need_lock) { \ - PTHREAD_MUTEX_UNLOCK(&(timer->slots + slot_index)->lock); \ - } \ - } while (0) - - #define TIMER_GET_SLOT_INDEX(timer, expires) \ (((expires) - timer->base_time) % timer->slot_count) @@ -147,7 +62,6 @@ void fast_timer_destroy(FastTimer *timer) static inline void add_entry(FastTimer *timer, FastTimerSlot *slot, FastTimerEntry *entry, const int64_t expires, const bool set_expires) { - TIMER_CHECK_LOCK_AND_SET_SLOT(timer, slot, entry); if (set_expires) { entry->expires = expires; } @@ -158,7 +72,6 @@ static inline void add_entry(FastTimer *timer, FastTimerSlot *slot, entry->prev = &slot->head; slot->head.next = entry; entry->rehash = false; - TIMER_CHECK_UNLOCK(timer, slot); } void fast_timer_add_ex(FastTimer *timer, FastTimerEntry *entry, @@ -179,58 +92,39 @@ void fast_timer_add_ex(FastTimer *timer, FastTimerEntry *entry, add_entry(timer, slot, entry, new_expires, new_set_expires); } -void fast_timer_modify(FastTimer *timer, FastTimerEntry *entry, +int fast_timer_modify(FastTimer *timer, FastTimerEntry *entry, const int64_t new_expires) { - int slot_index; - + int result; if (new_expires > entry->expires) { - if (timer->need_lock && entry->slot_index >= 0) { - slot_index = entry->slot_index; - if (slot_index < 0) { - slot_index = TIMER_GET_SLOT_INDEX(timer, entry->expires); - } - } else { - slot_index = TIMER_GET_SLOT_INDEX(timer, entry->expires); - } - - TIMER_CHECK_LOCK_BY_SINDEX(timer, slot_index); - entry->rehash = TIMER_GET_SLOT_INDEX(timer, new_expires) != slot_index; + entry->rehash = TIMER_GET_SLOT_INDEX(timer, new_expires) != + TIMER_GET_SLOT_INDEX(timer, entry->expires); entry->expires = new_expires; //lazy move - TIMER_CHECK_UNLOCK_BY_SINDEX(timer, slot_index); } else if (new_expires < entry->expires) { - fast_timer_remove(timer, entry); - fast_timer_add_ex(timer, entry, new_expires, true); + if ((result=fast_timer_remove(timer, entry)) == 0) { + fast_timer_add_ex(timer, entry, new_expires, true); + } + return result; } + return 0; } -static inline void remove_entry(FastTimerEntry *entry) +int fast_timer_remove(FastTimer *timer, FastTimerEntry *entry) { + if (entry->prev == NULL) { + return ENOENT; //already removed + } + if (entry->next != NULL) { entry->next->prev = entry->prev; entry->prev->next = entry->next; entry->next = NULL; - } - else { + } else { entry->prev->next = NULL; } entry->prev = NULL; -} - -int fast_timer_remove(FastTimer *timer, FastTimerEntry *entry) -{ - int result; - - TIMER_CHECK_LOCK_BY_ENTRY(timer, entry); - if (entry->prev == NULL) { - result = ENOENT; //already removed - } else { - remove_entry(entry); - result = 0; - } - TIMER_CHECK_UNLOCK_AND_REMOVE_BY_ENTRY(timer, entry); - return result; + return 0; } FastTimerSlot *fast_timer_slot_get(FastTimer *timer, const int64_t current_time) @@ -265,7 +159,6 @@ int fast_timer_timeouts_get(FastTimer *timer, const int64_t current_time, count = 0; while (timer->current_time < current_time) { slot = TIMER_GET_SLOT_POINTER(timer, timer->current_time++); - TIMER_CHECK_LOCK(timer, slot); entry = slot->head.next; while (entry != NULL) { if (entry->expires >= current_time) { //not expired @@ -284,9 +177,10 @@ int fast_timer_timeouts_get(FastTimer *timer, const int64_t current_time, new_slot = TIMER_GET_SLOT_POINTER(timer, last->expires); if (new_slot != slot) { //check to avoid deadlock - remove_entry(last); - add_entry(timer, new_slot, last, - last->expires, false); + if (fast_timer_remove(timer, last) == 0) { + add_entry(timer, new_slot, last, + last->expires, false); + } } else { last->rehash = false; } @@ -311,7 +205,6 @@ int fast_timer_timeouts_get(FastTimer *timer, const int64_t current_time, tail = last; first = NULL; } - TIMER_CHECK_UNLOCK(timer, slot); } if (count > 0) { diff --git a/src/fast_timer.h b/src/fast_timer.h index e040f691808013d9f4e3d3fb7f59180108642201..292894f4e8017730c829b4a64f5ec5d8885bc155 100644 --- a/src/fast_timer.h +++ b/src/fast_timer.h @@ -31,11 +31,9 @@ typedef struct fast_timer_entry { typedef struct fast_timer_slot { struct fast_timer_entry head; - pthread_mutex_t lock; } FastTimerSlot; typedef struct fast_timer { - bool need_lock; int slot_count; //time wheel slot count int64_t base_time; //base time for slot 0 int64_t current_time; @@ -46,20 +44,17 @@ typedef struct fast_timer { extern "C" { #endif -#define fast_timer_init(timer, slot_count, current_time) \ - fast_timer_init_ex(timer, slot_count, current_time, false) - #define fast_timer_add(timer, entry) \ fast_timer_add_ex(timer, entry, (entry)->expires, false) -int fast_timer_init_ex(FastTimer *timer, const int slot_count, - const int64_t current_time, const bool need_lock); +int fast_timer_init(FastTimer *timer, const int slot_count, + const int64_t current_time); void fast_timer_destroy(FastTimer *timer); void fast_timer_add_ex(FastTimer *timer, FastTimerEntry *entry, const int64_t expires, const bool set_expires); int fast_timer_remove(FastTimer *timer, FastTimerEntry *entry); -void fast_timer_modify(FastTimer *timer, FastTimerEntry *entry, +int fast_timer_modify(FastTimer *timer, FastTimerEntry *entry, const int64_t new_expires); FastTimerSlot *fast_timer_slot_get(FastTimer *timer, const int64_t current_time); diff --git a/src/locked_timer.c b/src/locked_timer.c index f8df8adbac1a457ff02049e54cb3f3d572b00402..839ee5830160541898f0adada7a24cba51e5b1a4 100644 --- a/src/locked_timer.c +++ b/src/locked_timer.c @@ -85,23 +85,24 @@ void locked_timer_destroy(LockedTimer *timer) pthread_mutex_t *lock; pthread_mutex_t *lend; - if (timer->slots != NULL) { - send = timer->slots + timer->slot_count; - for (slot=timer->slots; slotlock); - } - - lend = timer->entry_shares.locks + timer->entry_shares.count; - for (lock=timer->entry_shares.locks; lockentry_shares.locks); - timer->entry_shares.locks = NULL; - timer->entry_shares.count = 0; + if (timer->slots == NULL) { + return; + } + send = timer->slots + timer->slot_count; + for (slot=timer->slots; slotlock); + } - free(timer->slots); - timer->slots = NULL; + lend = timer->entry_shares.locks + timer->entry_shares.count; + for (lock=timer->entry_shares.locks; lockentry_shares.locks); + timer->entry_shares.locks = NULL; + timer->entry_shares.count = 0; + + free(timer->slots); + timer->slots = NULL; } #define TIMER_GET_SLOT_INDEX(timer, expires) \ @@ -110,10 +111,10 @@ void locked_timer_destroy(LockedTimer *timer) #define TIMER_GET_SLOT_POINTER(timer, expires) \ (timer->slots + TIMER_GET_SLOT_INDEX(timer, expires)) -#define LOCKED_TIMER_ENTRY_LOCK(timer, entry) \ +#define TIMER_ENTRY_LOCK(timer, entry) \ PTHREAD_MUTEX_LOCK(timer->entry_shares.locks + entry->lock_index) -#define LOCKED_TIMER_ENTRY_UNLOCK(timer, entry) \ +#define TIMER_ENTRY_UNLOCK(timer, entry) \ PTHREAD_MUTEX_UNLOCK(timer->entry_shares.locks + entry->lock_index) static inline void add_entry(LockedTimer *timer, LockedTimerSlot *slot, @@ -125,16 +126,15 @@ static inline void add_entry(LockedTimer *timer, LockedTimerSlot *slot, timer->entry_shares.count; } - LOCKED_TIMER_ENTRY_LOCK(timer, entry); + TIMER_ENTRY_LOCK(timer, entry); entry->status = FAST_TIMER_STATUS_NORMAL; entry->slot_index = slot - timer->slots; - LOCKED_TIMER_ENTRY_UNLOCK(timer, entry); + TIMER_ENTRY_UNLOCK(timer, entry); PTHREAD_MUTEX_LOCK(&slot->lock); if (set_expires) { entry->expires = expires; } - fc_list_add_tail(&entry->dlink, &slot->head); entry->rehash = false; PTHREAD_MUTEX_UNLOCK(&slot->lock); @@ -150,7 +150,7 @@ static inline int check_set_entry_status(LockedTimer *timer, int result; while (1) { - LOCKED_TIMER_ENTRY_LOCK(timer, entry); + TIMER_ENTRY_LOCK(timer, entry); switch (entry->status) { case FAST_TIMER_STATUS_CLEARED: result = ECANCELED; @@ -169,7 +169,7 @@ static inline int check_set_entry_status(LockedTimer *timer, break; } *slot_index = entry->slot_index; - LOCKED_TIMER_ENTRY_UNLOCK(timer, entry); + TIMER_ENTRY_UNLOCK(timer, entry); if (result == EAGAIN) { fc_sleep_ms(1); @@ -243,15 +243,6 @@ int locked_timer_remove_ex(LockedTimer *timer, LockedTimerEntry *entry, return 0; } -LockedTimerSlot *locked_timer_slot_get(LockedTimer *timer, const int64_t current_time) -{ - if (timer->current_time >= current_time) { - return NULL; - } - - return TIMER_GET_SLOT_POINTER(timer, timer->current_time++); -} - int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time, LockedTimerEntry *head) { @@ -278,14 +269,14 @@ int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time, if (entry->rehash) { new_slot = TIMER_GET_SLOT_POINTER(timer, entry->expires); if (new_slot != slot) { //check to avoid deadlock - LOCKED_TIMER_ENTRY_LOCK(timer, entry); + TIMER_ENTRY_LOCK(timer, entry); if (entry->status == FAST_TIMER_STATUS_NORMAL) { entry->status = FAST_TIMER_STATUS_MOVING; is_valid = true; } else { is_valid = false; } - LOCKED_TIMER_ENTRY_UNLOCK(timer, entry); + TIMER_ENTRY_UNLOCK(timer, entry); if (is_valid) { fc_list_del_init(&entry->dlink); @@ -297,14 +288,14 @@ int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time, } } } else { //expired - LOCKED_TIMER_ENTRY_LOCK(timer, entry); + TIMER_ENTRY_LOCK(timer, entry); if (entry->status == FAST_TIMER_STATUS_NORMAL) { entry->status = FAST_TIMER_STATUS_TIMEOUT; is_valid = true; } else { is_valid = false; } - LOCKED_TIMER_ENTRY_UNLOCK(timer, entry); + TIMER_ENTRY_UNLOCK(timer, entry); if (is_valid) { fc_list_del_init(&entry->dlink); diff --git a/src/locked_timer.h b/src/locked_timer.h index ffb90ca587c0ffdb7d06444499e8b8e05e2ff16c..8a512ca9b5a007512bbd07d477a2dd2625747a00 100644 --- a/src/locked_timer.h +++ b/src/locked_timer.h @@ -27,10 +27,9 @@ #define FAST_TIMER_STATUS_TIMEOUT 3 #define FAST_TIMER_STATUS_CLEARED 4 -struct locked_timer_slot; typedef struct locked_timer_entry { int64_t expires; - struct fc_list_head dlink; + struct fc_list_head dlink; //for timer slot struct locked_timer_entry *next; //for timeout chain uint32_t slot_index; //for slot lock uint16_t lock_index; //for entry lock @@ -50,7 +49,7 @@ typedef struct locked_timer_shared_locks { typedef struct locked_timer { int slot_count; //time wheel slot count - LockedTimerSharedLocks entry_shares; + LockedTimerSharedLocks entry_shares; //shared locks for entry int64_t base_time; //base time for slot 0 int64_t current_time; LockedTimerSlot *slots; @@ -80,7 +79,6 @@ int locked_timer_remove_ex(LockedTimer *timer, LockedTimerEntry *entry, int locked_timer_modify(LockedTimer *timer, LockedTimerEntry *entry, const int64_t new_expires); -LockedTimerSlot *locked_timer_slot_get(LockedTimer *timer, const int64_t current_time); int locked_timer_timeouts_get(LockedTimer *timer, const int64_t current_time, LockedTimerEntry *head);