summaryrefslogtreecommitdiff
path: root/maincontext.c
blob: 0edc79a6303a7175c1be264ab8f0cade81e2092e (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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "jobqueue.h"
#include "maincontext.h"
#include "mainloop.h"

/* A main context will generally correspond to one client in the server.
 *
 * Tasks added to it, either as fd tasks, or as idle/timeout tasks
 * will run serially, always.
 *
 * Parallelism can be done through the - as yet - non-existant
 * get_executor(). Or perhaps, create_job_queue()? 
 *
 * Also, given a main context, who really needs a "mainloop"? How about
 * just passing in an epoll and an executor at creation time?
 *
 * Sounds like a better idea. Hmm, the problem is who calls epoll_wait()?
 *
 * Also should probably have a main_context_get_data() and then pass the
 * context to the callbacks, rather than the data directly. This way
 * the callbacks have acess to the context as well. Though I guess the
 * user data will generally contain a pointer to the context. So data
 * itself is probably more convenient. Or is it? If you have data, then
 * you have to do my_stuff->context to get at the context, if it is an
 * argument, then you can just use it. Ie., there is no useless "data"
 * parameter.
 *
 * We will most likely need per-fd data for things like Connections.
 */
typedef struct ContextFdInfo ContextFdInfo;

struct MainContext
{
    MainLoop *	loop;
    gpointer	data;
    JobQueue *	job_queue;
};

struct ContextFdInfo
{
    MainContext	*	context;
    MainFdTask		prepare;
    MainFdTask		read;
    MainFdTask		write;
    gpointer		data;
};

MainContext *
main_context_new (MainLoop *loop,
		  gpointer  data)
{
    MainContext *context = g_new0 (MainContext, 1);

    context->loop = loop;
    context->data = data;
    context->job_queue = job_queue_new (main_loop_get_executor (loop));
    
    return context;
}

void
main_context_free (MainContext *context)
{
    /* FIXME: this will complain if we run it when there are still
     * active jobs. But we kinda have to delete the job out of a
     * task that runs in it. So what do we do? Maybe just make it
     * legal to delete an active job queue. I don't really see the
     * harm in that, except that the execution function in jobqueue.c
     * might get a little bit more complex
     */
    
    job_queue_free (context->job_queue);
    
    g_free (context);
}

static void
on_fd_activity (int fd,
		EPollEventType mask,
		gpointer data)
{
    
}

/* Filedescriptors */
void
main_context_add_fd		(MainContext	*context,
				 int		 fd,
				 gpointer	 data)
{
    ContextFdInfo *info = g_new0 (ContextFdInfo, 1);

    info->context = context;
    info->data = data;
    info->prepare = NULL;
    info->read = NULL;
    info->write = NULL;
    
    main_loop_add_fd (context->loop,
		      fd,
		      context->job_queue,
		      on_fd_activity,
		      info);
}

void
main_context_remove_fd		(MainContext    *context,
				 int		 fd)
{
    
}

static void
update_poll_mask (MainContext   *context,
		  ContextFdInfo *info,
		  int	         fd)
{
    
}

/* Called before the fd is polled */
void
main_context_set_prepare_callback (MainContext  *context,
				   int		 fd,
				   MainFdTask    func)
{
    
}

/* Called when the fd is writable */
void
main_context_set_write_callback (MainContext	*context,
				 int		 fd,
				 MainFdTask	 func)
{
    
}

/* Called when there is data to be read, if the fd is closed/hungup, or
 * if there is an error
 */
void
main_context_set_read_callback (MainContext  *context,
				int		fd,
				MainFdTask    func)
{
    
}

/* Idle/timeout tasks */
#if 0
typedef gboolean (* MainTaskFunc) (gpointer data);

MainTask *
main_context_add_idle		(MainContext	*context,
				 MainTaskFunc	 func,
				 gpointer	 data)
{

}

MainTask *
main_context_add_timeout	(MainContext	*context,
				 int		 millisecs,
				 MainTaskFunc	 func,
				 gpointer	 data)
{

}

void
main_task_remove		(MainTask	*task)
{
    
}
#endif