summaryrefslogtreecommitdiffstats
path: root/src/knot/common/evsched.h
blob: 762c3f87d9036277ae83a263211505727c78b875 (plain)
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*  Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

/*!
 * \brief Event scheduler.
 */

#pragma once

#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/time.h>

#include "knot/server/dthreads.h"
#include "contrib/ucw/heap.h"

/* Forward decls. */
struct evsched;
struct event;

/*!
 * \brief Event callback.
 *
 * Pointer to whole event structure is passed to the callback.
 * Callback should return 0 on success and negative integer on error.
 *
 * Example callback:
 * \code
 * void print_callback(event_t *t) {
 *    printf("Callback: %s\n", t->data);
 * }
 * \endcode
 */
typedef void (*event_cb_t)(struct event *);

/*!
 * \brief Event structure.
 */
typedef struct event {
	struct heap_val hpos;
	struct timeval tv; /*!< Event scheduled time. */
	void *data;        /*!< Usable data ptr. */
	event_cb_t cb;     /*!< Event callback. */
	struct evsched *sched; /*!< Scheduler for this event. */
} event_t;

/*!
 * \brief Event scheduler structure.
 */
typedef struct evsched {
	volatile bool paused;      /*!< Temporarily stop processing events. */
	pthread_mutex_t heap_lock; /*!< Event heap locking. */
	pthread_cond_t notify;     /*!< Event heap notification. */
	struct heap heap;          /*!< Event heap. */
	void *ctx;                 /*!< Scheduler context. */
	dt_unit_t *thread;
} evsched_t;

/*!
 * \brief Initialize event scheduler instance.
 *
 * \retval New instance on success.
 * \retval NULL on error.
 */
int evsched_init(evsched_t *sched, void *ctx);

/*!
 * \brief Deinitialize and free event scheduler instance.
 *
 * \param sched Pointer to event scheduler instance.
 */
void evsched_deinit(evsched_t *sched);

/*!
 * \brief Create a callback event.
 *
 * \note Scheduler takes ownership of scheduled events. Created, but unscheduled
 *       events are in the ownership of the caller.
 *
 * \param sched Pointer to event scheduler instance.
 * \param cb Callback handler.
 * \param data Data for callback.
 *
 * \retval New instance on success.
 * \retval NULL on error.
 */
event_t *evsched_event_create(evsched_t *sched, event_cb_t cb, void *data);

/*!
 * \brief Dispose event instance.
 *
 * \param ev Event instance.
 */
void evsched_event_free(event_t *ev);

/*!
 * \brief Schedule an event.
 *
 * \note This function checks if the event was already scheduled, if it was
 *       then it replaces this timer with the newer value.
 *       Running events are not canceled or waited for.
 *
 * \param ev Prepared event.
 * \param dt Time difference in milliseconds from now (dt is relative).
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_EINVAL
 */
int evsched_schedule(event_t *ev, uint32_t dt);

/*!
 * \brief Cancel a scheduled event.
 *
 * \warning May block until current running event is finished (as it cannot
 *          interrupt running event).
 *
 * \warning Never cancel event in it's callback. As it never finishes,
 *          it deadlocks.
 *
 * \param ev Scheduled event.
 *
 * \retval KNOT_EOK
 * \retval KNOT_EINVAL
 */
int evsched_cancel(event_t *ev);

/*! \brief Start event processing threads. */
void evsched_start(evsched_t *sched);

/*! \brief Stop event processing threads. */
void evsched_stop(evsched_t *sched);

/*! \brief Join event processing threads. */
void evsched_join(evsched_t *sched);

/*! \brief Temporarily stop processing events. */
void evsched_pause(evsched_t *sched);

/*! \brief Resume processing events. */
void evsched_resume(evsched_t *sched);