Changeset 3034 for pjproject/trunk
- Timestamp:
- Dec 16, 2009 1:30:34 PM (15 years ago)
- Location:
- pjproject/trunk/pjlib
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/include/pj/timer.h
r2512 r3034 65 65 * The type for internal timer ID. 66 66 */ 67 #if defined(PJ_SYMBIAN) && PJ_SYMBIAN!=068 typedef void *pj_timer_id_t;69 #else70 67 typedef int pj_timer_id_t; 71 #endif72 68 73 69 /** -
pjproject/trunk/pjlib/src/pj/timer_symbian.cpp
r2984 r3034 32 32 #define MAX_RTIMER_INTERVAL 2147 33 33 34 /* Absolute maximum number of timer entries */ 35 #ifndef PJ_SYMBIAN_TIMER_MAX_COUNT 36 # define PJ_SYMBIAN_TIMER_MAX_COUNT 65535 37 #endif 38 39 /* Get the number of free slots in the timer heap */ 40 #define FREECNT(th) (th->max_size - th->cur_size) 41 42 // Forward declaration 43 class CPjTimerEntry; 34 44 35 45 /** … … 44 54 pj_size_t cur_size; 45 55 46 /** Max timed out entries to process per poll. */ 47 unsigned max_entries_per_poll; 56 /** Array of timer entries. A scheduled timer will occupy one slot, and 57 * the slot number will be saved in entry->_timer_id 58 */ 59 CPjTimerEntry **entries; 60 61 /** Array of free slot indexes in the "entries" array */ 62 int *free_slots; 48 63 }; 49 64 50 51 //////////////////////////////////////////////////////////////////////////////52 65 /** 53 66 * Active object for each timer entry. … … 56 69 { 57 70 public: 71 pj_timer_entry *entry_; 72 58 73 static CPjTimerEntry* NewL( pj_timer_heap_t *timer_heap, 59 74 pj_timer_entry *entry, … … 67 82 private: 68 83 pj_timer_heap_t *timer_heap_; 69 pj_timer_entry *entry_;70 84 RTimer rtimer_; 71 85 pj_uint32_t interval_left_; … … 76 90 }; 77 91 92 ////////////////////////////////////////////////////////////////////////////// 93 /* 94 * Implementation. 95 */ 96 97 /* Grow timer heap to the specified size */ 98 static pj_status_t realloc_timer_heap(pj_timer_heap_t *th, pj_size_t new_size) 99 { 100 typedef CPjTimerEntry *entry_ptr; 101 CPjTimerEntry **entries = NULL; 102 int *free_slots = NULL; 103 unsigned i, j; 104 105 if (new_size > PJ_SYMBIAN_TIMER_MAX_COUNT) { 106 /* Just some sanity limit */ 107 new_size = PJ_SYMBIAN_TIMER_MAX_COUNT; 108 if (new_size <= th->max_size) { 109 /* We've grown large enough */ 110 pj_assert(!"Too many timer heap entries"); 111 return PJ_ETOOMANY; 112 } 113 } 114 115 /* Allocate entries, move entries from the old array if there is one */ 116 entries = new entry_ptr[new_size]; 117 if (th->entries) { 118 pj_memcpy(entries, th->entries, th->max_size * sizeof(th->entries[0])); 119 } 120 /* Initialize the remaining new area */ 121 pj_bzero(&entries[th->max_size], 122 (new_size - th->max_size) * sizeof(th->entries[0])); 123 124 /* Allocate free slots array */ 125 free_slots = new int[new_size]; 126 if (th->free_slots) { 127 pj_memcpy(free_slots, th->free_slots, 128 FREECNT(th) * sizeof(th->free_slots[0])); 129 } 130 /* Initialize the remaining new area */ 131 for (i=FREECNT(th), j=th->max_size; j<new_size; ++i, ++j) { 132 free_slots[i] = j; 133 } 134 for ( ; i<new_size; ++i) { 135 free_slots[i] = -1; 136 } 137 138 /* Apply */ 139 delete [] th->entries; 140 th->entries = entries; 141 th->max_size = new_size; 142 delete [] th->free_slots; 143 th->free_slots = free_slots; 144 145 return PJ_SUCCESS; 146 } 147 148 /* Allocate and register an entry to timer heap for newly scheduled entry */ 149 static pj_status_t add_entry(pj_timer_heap_t *th, CPjTimerEntry *entry) 150 { 151 pj_status_t status; 152 int slot; 153 154 /* Check that there's still capacity left in the timer heap */ 155 if (FREECNT(th) < 1) { 156 // Grow the timer heap twice the capacity 157 status = realloc_timer_heap(th, th->max_size * 2); 158 if (status != PJ_SUCCESS) 159 return status; 160 } 161 162 /* Allocate one free slot. Use LIFO */ 163 slot = th->free_slots[FREECNT(th)-1]; 164 PJ_ASSERT_RETURN((slot >= 0) && (slot < (int)th->max_size) && 165 (th->entries[slot]==NULL), PJ_EBUG); 166 167 th->free_slots[FREECNT(th)-1] = -1; 168 th->entries[slot] = entry; 169 entry->entry_->_timer_id = slot; 170 ++th->cur_size; 171 172 return PJ_SUCCESS; 173 } 174 175 /* Free a slot when an entry's timer has elapsed or cancel */ 176 static pj_status_t remove_entry(pj_timer_heap_t *th, CPjTimerEntry *entry) 177 { 178 int slot = entry->entry_->_timer_id; 179 180 PJ_ASSERT_RETURN(slot >= 0 && slot < (int)th->max_size, PJ_EBUG); 181 PJ_ASSERT_RETURN(FREECNT(th) < th->max_size, PJ_EBUG); 182 PJ_ASSERT_RETURN(th->entries[slot]==entry, PJ_EBUG); 183 PJ_ASSERT_RETURN(th->free_slots[FREECNT(th)]==-1, PJ_EBUG); 184 185 th->entries[slot] = NULL; 186 th->free_slots[FREECNT(th)] = slot; 187 entry->entry_->_timer_id = -1; 188 --th->cur_size; 189 190 return PJ_SUCCESS; 191 } 192 78 193 79 194 CPjTimerEntry::CPjTimerEntry(pj_timer_heap_t *timer_heap, 80 195 pj_timer_entry *entry) 81 : CActive(PJ_SYMBIAN_TIMER_PRIORITY), timer_heap_(timer_heap), entry_(entry),196 : CActive(PJ_SYMBIAN_TIMER_PRIORITY), entry_(entry), timer_heap_(timer_heap), 82 197 interval_left_(0) 83 198 { … … 133 248 } 134 249 135 --timer_heap_->cur_size; 136 entry_->_timer_id = NULL; 250 remove_entry(timer_heap_, this); 137 251 entry_->cb(timer_heap_, entry_); 138 252 … … 143 257 void CPjTimerEntry::DoCancel() 144 258 { 145 rtimer_.Cancel(); 259 /* It's possible that _timer_id is -1, see schedule(). In this case, 260 * the entry has not been added to the timer heap, so don't remove 261 * it. 262 */ 263 if (entry_ && entry_->_timer_id != -1) 264 remove_entry(timer_heap_, this); 265 266 rtimer_.Cancel(); 146 267 } 147 268 … … 158 279 sizeof(pj_timer_heap_t) + 159 280 /* size of each entry: */ 160 (count+2) * (sizeof( pj_timer_entry*)+sizeof(pj_timer_id_t)) +281 (count+2) * (sizeof(void*)+sizeof(int)) + 161 282 /* lock, pool etc: */ 162 283 132; … … 171 292 { 172 293 pj_timer_heap_t *ht; 294 pj_status_t status; 173 295 174 296 PJ_ASSERT_RETURN(pool && p_heap, PJ_EINVAL); … … 177 299 178 300 /* Allocate timer heap data structure from the pool */ 179 ht = PJ_POOL_ ALLOC_T(pool, pj_timer_heap_t);301 ht = PJ_POOL_ZALLOC_T(pool, pj_timer_heap_t); 180 302 if (!ht) 181 303 return PJ_ENOMEM; 182 304 183 /* Initialize timer heap sizes */184 ht->max_size = size;185 ht->cur_size = 0;186 ht->max_entries_per_poll = DEFAULT_MAX_TIMED_OUT_PER_POLL;305 /* Allocate slots */ 306 status = realloc_timer_heap(ht, size); 307 if (status != PJ_SUCCESS) 308 return status; 187 309 188 310 *p_heap = ht; … … 192 314 PJ_DEF(void) pj_timer_heap_destroy( pj_timer_heap_t *ht ) 193 315 { 194 PJ_UNUSED_ARG(ht); 316 /* Cancel and delete pending active objects */ 317 if (ht->entries) { 318 unsigned i; 319 for (i=0; i<ht->max_size; ++i) { 320 if (ht->entries[i]) { 321 ht->entries[i]->Cancel(); 322 delete ht->entries[i]; 323 ht->entries[i] = NULL; 324 } 325 } 326 } 327 328 delete [] ht->entries; 329 delete [] ht->free_slots; 330 331 ht->entries = NULL; 332 ht->free_slots = NULL; 195 333 } 196 334 … … 208 346 unsigned count ) 209 347 { 210 unsigned old_count = ht->max_entries_per_poll;211 ht->max_entries_per_poll = count;212 return old_count;348 /* Not applicable */ 349 PJ_UNUSED_ARG(count); 350 return ht->max_size; 213 351 } 214 352 … … 220 358 pj_assert(entry && cb); 221 359 222 entry->_timer_id = NULL;360 entry->_timer_id = -1; 223 361 entry->id = id; 224 362 entry->user_data = user_data; … … 233 371 { 234 372 CPjTimerEntry *timerObj; 373 pj_status_t status; 235 374 236 375 PJ_ASSERT_RETURN(ht && entry && delay, PJ_EINVAL); … … 238 377 239 378 /* Prevent same entry from being scheduled more than once */ 240 PJ_ASSERT_RETURN(entry->_timer_id == NULL, PJ_EINVALIDOP); 241 379 PJ_ASSERT_RETURN(entry->_timer_id < 1, PJ_EINVALIDOP); 380 381 entry->_timer_id = -1; 382 242 383 timerObj = CPjTimerEntry::NewL(ht, entry, delay); 243 entry->_timer_id = (void*) timerObj; 244 245 ++ht->cur_size; 384 status = add_entry(ht, timerObj); 385 if (status != PJ_SUCCESS) { 386 timerObj->Cancel(); 387 delete timerObj; 388 return status; 389 } 390 246 391 return PJ_SUCCESS; 247 392 } … … 252 397 PJ_ASSERT_RETURN(ht && entry, PJ_EINVAL); 253 398 254 if (entry->_timer_id != NULL) { 255 CPjTimerEntry *timerObj = (CPjTimerEntry*) entry->_timer_id; 256 timerObj->Cancel(); 257 delete timerObj; 258 entry->_timer_id = NULL; 259 --ht->cur_size; 260 return 1; 399 if (entry->_timer_id >= 0 && entry->_timer_id < (int)ht->max_size) { 400 CPjTimerEntry *timerObj = ht->entries[entry->_timer_id]; 401 if (timerObj) { 402 timerObj->Cancel(); 403 delete timerObj; 404 return 1; 405 } else { 406 return 0; 407 } 261 408 } else { 262 409 return 0;
Note: See TracChangeset
for help on using the changeset viewer.