blob: 2daf8afaea5f9de127f664e899c362caa6c41be6 [file] [log] [blame]
Benny Prijonob2c96822007-05-03 13:31:21 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijonob2c96822007-05-03 13:31:21 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pj/timer.h>
21#include <pj/pool.h>
22#include <pj/assert.h>
23#include <pj/errno.h>
24#include <pj/lock.h>
25
26#include "os_symbian.h"
27
28
29#define DEFAULT_MAX_TIMED_OUT_PER_POLL (64)
30
31
32/**
33 * The implementation of timer heap.
34 */
35struct pj_timer_heap_t
36{
37 /** Maximum size of the heap. */
38 pj_size_t max_size;
39
40 /** Current size of the heap. */
41 pj_size_t cur_size;
42
43 /** Max timed out entries to process per poll. */
44 unsigned max_entries_per_poll;
45};
46
47
48//////////////////////////////////////////////////////////////////////////////
49/**
50 * Active object for each timer entry.
51 */
52class CPjTimerEntry : public CActive
53{
54public:
55 static CPjTimerEntry* NewL( pj_timer_heap_t *timer_heap,
56 pj_timer_entry *entry,
57 const pj_time_val *delay);
58
59 ~CPjTimerEntry();
60
61 virtual void RunL();
62 virtual void DoCancel();
63
64private:
65 pj_timer_heap_t *timer_heap_;
66 pj_timer_entry *entry_;
67 RTimer rtimer_;
68
69 CPjTimerEntry(pj_timer_heap_t *timer_heap, pj_timer_entry *entry);
70 void ConstructL(const pj_time_val *delay);
71};
72
73
74CPjTimerEntry::CPjTimerEntry(pj_timer_heap_t *timer_heap,
75 pj_timer_entry *entry)
76: CActive(PJ_SYMBIAN_TIMER_PRIORITY), timer_heap_(timer_heap), entry_(entry)
77{
78}
79
80CPjTimerEntry::~CPjTimerEntry()
81{
Nanang Izzuddin82f7a412008-12-17 11:36:22 +000082 Cancel();
Benny Prijonob2c96822007-05-03 13:31:21 +000083 rtimer_.Close();
84}
85
86void CPjTimerEntry::ConstructL(const pj_time_val *delay)
87{
88 rtimer_.CreateLocal();
89 CActiveScheduler::Add(this);
90
Benny Prijono897f9f82007-05-03 19:56:21 +000091 pj_int32_t interval = PJ_TIME_VAL_MSEC(*delay) * 1000;
92 if (interval < 0) {
93 interval = 0;
94 }
95 rtimer_.After(iStatus, interval);
Benny Prijonob2c96822007-05-03 13:31:21 +000096 SetActive();
97}
98
99CPjTimerEntry* CPjTimerEntry::NewL(pj_timer_heap_t *timer_heap,
100 pj_timer_entry *entry,
101 const pj_time_val *delay)
102{
103 CPjTimerEntry *self = new CPjTimerEntry(timer_heap, entry);
104 CleanupStack::PushL(self);
105 self->ConstructL(delay);
106 CleanupStack::Pop(self);
107
108 return self;
109}
110
111void CPjTimerEntry::RunL()
112{
113 --timer_heap_->cur_size;
114 entry_->_timer_id = NULL;
115 entry_->cb(timer_heap_, entry_);
116
117 // Finger's crossed!
118 delete this;
119}
120
121void CPjTimerEntry::DoCancel()
122{
123 rtimer_.Cancel();
124}
125
126
127//////////////////////////////////////////////////////////////////////////////
128
129
130/*
131 * Calculate memory size required to create a timer heap.
132 */
133PJ_DEF(pj_size_t) pj_timer_heap_mem_size(pj_size_t count)
134{
135 return /* size of the timer heap itself: */
136 sizeof(pj_timer_heap_t) +
137 /* size of each entry: */
138 (count+2) * (sizeof(pj_timer_entry*)+sizeof(pj_timer_id_t)) +
139 /* lock, pool etc: */
140 132;
141}
142
143/*
144 * Create a new timer heap.
145 */
146PJ_DEF(pj_status_t) pj_timer_heap_create( pj_pool_t *pool,
147 pj_size_t size,
148 pj_timer_heap_t **p_heap)
149{
150 pj_timer_heap_t *ht;
151
152 PJ_ASSERT_RETURN(pool && p_heap, PJ_EINVAL);
153
154 *p_heap = NULL;
155
156 /* Allocate timer heap data structure from the pool */
157 ht = PJ_POOL_ALLOC_T(pool, pj_timer_heap_t);
158 if (!ht)
159 return PJ_ENOMEM;
160
161 /* Initialize timer heap sizes */
162 ht->max_size = size;
163 ht->cur_size = 0;
164 ht->max_entries_per_poll = DEFAULT_MAX_TIMED_OUT_PER_POLL;
165
166 *p_heap = ht;
167 return PJ_SUCCESS;
168}
169
170PJ_DEF(void) pj_timer_heap_destroy( pj_timer_heap_t *ht )
171{
172 PJ_UNUSED_ARG(ht);
173}
174
175PJ_DEF(void) pj_timer_heap_set_lock( pj_timer_heap_t *ht,
176 pj_lock_t *lock,
177 pj_bool_t auto_del )
178{
179 PJ_UNUSED_ARG(ht);
180 if (auto_del)
181 pj_lock_destroy(lock);
182}
183
184
185PJ_DEF(unsigned) pj_timer_heap_set_max_timed_out_per_poll(pj_timer_heap_t *ht,
186 unsigned count )
187{
188 unsigned old_count = ht->max_entries_per_poll;
189 ht->max_entries_per_poll = count;
190 return old_count;
191}
192
193PJ_DEF(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry,
194 int id,
195 void *user_data,
196 pj_timer_heap_callback *cb )
197{
198 pj_assert(entry && cb);
199
200 entry->_timer_id = NULL;
201 entry->id = id;
202 entry->user_data = user_data;
203 entry->cb = cb;
204
205 return entry;
206}
207
208PJ_DEF(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht,
209 pj_timer_entry *entry,
210 const pj_time_val *delay)
211{
212 CPjTimerEntry *timerObj;
213
214 PJ_ASSERT_RETURN(ht && entry && delay, PJ_EINVAL);
215 PJ_ASSERT_RETURN(entry->cb != NULL, PJ_EINVAL);
216
217 /* Prevent same entry from being scheduled more than once */
218 PJ_ASSERT_RETURN(entry->_timer_id == NULL, PJ_EINVALIDOP);
219
220 timerObj = CPjTimerEntry::NewL(ht, entry, delay);
221 entry->_timer_id = (void*) timerObj;
222
223 ++ht->cur_size;
224 return PJ_SUCCESS;
225}
226
227PJ_DEF(int) pj_timer_heap_cancel( pj_timer_heap_t *ht,
228 pj_timer_entry *entry)
229{
230 PJ_ASSERT_RETURN(ht && entry, PJ_EINVAL);
231
232 if (entry->_timer_id != NULL) {
233 CPjTimerEntry *timerObj = (CPjTimerEntry*) entry->_timer_id;
234 timerObj->Cancel();
235 delete timerObj;
236 entry->_timer_id = NULL;
237 --ht->cur_size;
238 return 1;
239 } else {
240 return 0;
241 }
242}
243
244PJ_DEF(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht,
245 pj_time_val *next_delay )
246{
247 /* Polling is not necessary on Symbian, since all async activities
248 * are registered to active scheduler.
249 */
250 PJ_UNUSED_ARG(ht);
251 if (next_delay) {
252 next_delay->sec = 1;
253 next_delay->msec = 0;
254 }
255 return 0;
256}
257
258PJ_DEF(pj_size_t) pj_timer_heap_count( pj_timer_heap_t *ht )
259{
260 PJ_ASSERT_RETURN(ht, 0);
261
262 return ht->cur_size;
263}
264
265PJ_DEF(pj_status_t) pj_timer_heap_earliest_time( pj_timer_heap_t * ht,
266 pj_time_val *timeval)
267{
268 /* We don't support this! */
269 PJ_UNUSED_ARG(ht);
270
271 timeval->sec = 1;
272 timeval->msec = 0;
273
274 return PJ_SUCCESS;
275}
276