use status bar widget
[prss.git] / src / ttrss_wsasync.c
1 /*
2  * Copyright (C) 2010-2013 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23
24 #include <pthread.h>
25
26 #include <json/json.h>
27
28 #include "list.h"
29 #include "log.h"
30 #include "ttrss_ws.h"
31 #include "ttrss_wsasync.h"
32
33 struct async_request {
34         void *data;
35         struct json_object *request;
36         void (*callback)(struct json_object *, void *);
37 };
38
39 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
40
41 static struct async_request **requests;
42
43 static pthread_t *thread;
44
45 static void async_request_free(struct async_request *rq)
46 {
47         if (rq) {
48                 if (rq->request)
49                         json_object_put(rq->request);
50                 free(rq);
51         }
52 }
53
54 static void *loop()
55 {
56         struct json_object *rp;
57         struct async_request **tmp, **cur, *rq;
58
59         while (1) {
60                 log_debug("loop()");
61
62                 pthread_mutex_lock(&lock);
63                 if (requests) {
64                         tmp = requests;
65                         requests = NULL;
66                 } else {
67                         tmp = NULL;
68                 }
69                 pthread_mutex_unlock(&lock);
70
71                 if (tmp) {
72                         cur = tmp;
73                         while (*cur) {
74                                 rq = *cur;
75                                 rp = ws_execute(rq->request);
76
77                                 if (rq->callback)
78                                         rq->callback(rp, rq->data);
79
80                                 async_request_free(rq);
81                                 if (rp)
82                                         json_object_put(rp);
83
84                                 cur++;
85                                 usleep(500000);
86                         }
87                         free(tmp);
88                 }
89
90                 log_debug("loop() done");
91                 sleep(1);
92         }
93
94         pthread_exit(NULL);
95 }
96
97 static struct async_request *
98 add_async_request(struct json_object *rq,
99                   void (*callback)(struct json_object *, void *data),
100                   void *data)
101 {
102         struct async_request *async_rq;
103         struct async_request **tmp;
104
105         pthread_mutex_lock(&lock);
106         if (!thread) {
107                 thread = malloc(sizeof(pthread_t));
108                 pthread_create(thread, NULL, loop, NULL);
109         }
110         pthread_mutex_unlock(&lock);
111
112         async_rq = malloc(sizeof(struct async_request));
113         async_rq->request = rq;
114         async_rq->data = data;
115         async_rq->callback = callback;
116
117         pthread_mutex_lock(&lock);
118         tmp = (struct async_request **)list_add((void **)requests, async_rq);
119         list_free((void **)requests);
120         requests = tmp;
121         pthread_mutex_unlock(&lock);
122
123         return async_rq;
124 }
125
126 void ws_async_set_article_unread(int id, int unread)
127 {
128         struct json_object *rq;
129
130         log_debug("ws_async_set_article_unread(%d,%d)", id, unread);
131
132         rq = ws_request_new_set_article_unread(id, unread);
133
134         add_async_request(rq, NULL, NULL);
135
136         log_debug("ws_async_set_article_unread(%d,%d) done", id, unread);
137 }
138
139 struct cbk_data {
140         int id;
141         void (*callback)(int id, const char *);
142 };
143
144 void async_article_content_cbk(struct json_object *rp, void *userdata)
145 {
146         struct cbk_data *data;
147
148         data = userdata;
149
150         log_debug("async_article_content_cbk %d\n", data->id);
151
152         if (data->callback)
153                 data->callback(data->id, ws_reply_get_article_content(rp));
154
155         free(data);
156 }
157
158
159 void
160 ws_async_get_article_content(int id, void (*callback)(int id, const char *))
161 {
162         struct json_object *rq;
163         struct cbk_data *data;
164
165         rq = ws_request_new_get_article_content(id);
166
167         data = malloc(sizeof(struct cbk_data));
168         data->id = id;
169         data->callback = callback;
170
171         add_async_request(rq, async_article_content_cbk, data);
172 }