File: timerthread.h

package info (click to toggle)
rtpengine 13.5.1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,676 kB
  • sloc: ansic: 86,764; perl: 59,422; python: 3,193; sh: 1,030; makefile: 693; asm: 211
file content (97 lines) | stat: -rw-r--r-- 2,856 bytes parent folder | download
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
#ifndef _TIMERTHREAD_H_
#define _TIMERTHREAD_H_

#include <glib.h>
#include <sys/time.h>

#include "auxlib.h"
#include "obj.h"

struct timerthread;

struct timerthread_thread {
	struct timerthread *parent;
	GTree *tree; // XXX investigate other structures
	mutex_t lock;
	cond_t cond;
	int64_t next_wake;
	struct timerthread_obj *obj;
};

struct timerthread {
	unsigned int num_threads;
	struct timerthread_thread *threads;
	unsigned int thread_idx;
	void (*func)(void *);
};

struct timerthread_obj {
	struct obj obj;

	struct timerthread *tt;
	struct timerthread_thread *thread; // set once and then static
	int64_t next_check; /* protected by ->lock */
	int64_t last_run; /* ditto */
};

struct timerthread_queue {
	struct timerthread_obj tt_obj;
	const char *type;
	mutex_t lock;
	GTree *entries;
	void (*run_now_func)(struct timerthread_queue *, void *);
	void (*run_later_func)(struct timerthread_queue *, void *);
	void (*free_func)(void *);
	void (*entry_free_func)(void *);
};

struct timerthread_queue_entry {
	int64_t when;
	unsigned int idx; // for equal timestamps
	void *source; // opaque
	char __rest[0];
};


void timerthread_init(struct timerthread *, unsigned int, void (*)(void *));
void timerthread_free(struct timerthread *);
void timerthread_launch(struct timerthread *, const char *scheduler, int prio, const char *name);

void timerthread_obj_schedule_abs_nl(struct timerthread_obj *, const int64_t);
void timerthread_obj_deschedule(struct timerthread_obj *);

// run_now_func = called if newly inserted object can be processed immediately by timerthread_queue_push within its calling context
// run_later_func = called from the separate timer thread
void *timerthread_queue_new(const char *type, size_t size,
		struct timerthread *tt,
		void (*run_now_func)(struct timerthread_queue *, void *),
		void (*run_later_func)(struct timerthread_queue *, void *), // optional
		void (*free_func)(void *),
		void (*entry_free_func)(void *));
void timerthread_queue_run(void *ptr);
void timerthread_queue_flush_data(void *ptr);
void timerthread_queue_push(struct timerthread_queue *, struct timerthread_queue_entry *);
unsigned int timerthread_queue_flush(struct timerthread_queue *, void *);

INLINE struct timerthread_thread *timerthread_get_next(struct timerthread *tt) {
	unsigned int idx = g_atomic_int_add(&tt->thread_idx, 1);
	idx = idx % tt->num_threads; // XXX check perf without %
	return &tt->threads[idx];
}

INLINE void timerthread_obj_schedule_abs(struct timerthread_obj *tt_obj, const int64_t tv) {
	if (!tt_obj)
		return;
	struct timerthread_thread *tt = tt_obj->thread;
	if (!tt) {
		tt = timerthread_get_next(tt_obj->tt);
		g_atomic_pointer_compare_and_exchange(&tt_obj->thread, NULL, tt);
	}
	tt = tt_obj->thread;
	mutex_lock(&tt->lock);
	timerthread_obj_schedule_abs_nl(tt_obj, tv);
	mutex_unlock(&tt->lock);
}


#endif