1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
*
*/
#include <ell/ell.h>
#include "timeout.h"
static struct l_queue *timeout_q;
struct timeout_data {
timeout_func_t func;
timeout_destroy_func_t destroy;
void *user_data;
unsigned int timeout;
};
static bool match_id(const void *a, const void *b)
{
unsigned int to_id = L_PTR_TO_UINT(a);
unsigned int id = L_PTR_TO_UINT(b);
return (to_id == id);
}
static void timeout_callback(struct l_timeout *timeout, void *user_data)
{
struct timeout_data *data = user_data;
if (data->func)
data->func(data->user_data);
l_timeout_modify(timeout, data->timeout);
}
static void timeout_destroy(void *user_data)
{
struct timeout_data *data = user_data;
if (data->destroy)
data->destroy(data->user_data);
l_free(data);
}
unsigned int timeout_add(unsigned int timeout, timeout_func_t func,
void *user_data, timeout_destroy_func_t destroy)
{
struct timeout_data *data;
unsigned int id = 0;
struct l_timeout *to;
int tries = 0;
if (!timeout_q)
timeout_q = l_queue_new();
data = l_new(struct timeout_data, 1);
data->func = func;
data->destroy = destroy;
data->user_data = user_data;
data->timeout = timeout;
while (id == 0 && tries < 3) {
to = l_timeout_create_ms(timeout, timeout_callback,
data, timeout_destroy);
if (!to)
break;
tries++;
id = L_PTR_TO_UINT(to);
if (id == 0 ||
l_queue_find(timeout_q, match_id, L_UINT_TO_PTR(id))) {
l_timeout_remove(to);
continue;
}
l_queue_push_tail(timeout_q, to);
}
if (id == 0)
l_free(data);
return id;
}
void timeout_remove(unsigned int id)
{
struct l_timeout *to;
to = l_queue_remove_if(timeout_q, match_id, L_UINT_TO_PTR(id));
if (to)
l_timeout_remove(to);
}
unsigned int timeout_add_seconds(unsigned int timeout, timeout_func_t func,
void *user_data, timeout_destroy_func_t destroy)
{
return timeout_add(timeout * 1000, func, user_data, destroy);
}
|