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