(no commit message)
[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 <stdlib.h>
21 #include <unistd.h>
22
23 #include <pthread.h>
24
25 #include <json/json.h>
26
27 #include "list.h"
28 #include "log.h"
29 #include "ttrss_ws.h"
30 #include "ttrss_wsasync.h"
31
32 struct async_request {
33         void *data;
34         struct json_object *request;
35         void (*callback)(struct json_object *, void *);
36 };
37
38 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
39
40 static struct async_request **requests;
41
42 static pthread_t *thread;
43
44 static void async_request_free(struct async_request *rq)
45 {
46         if (rq) {
47                 if (rq->request)
48                         json_object_put(rq->request);
49                 free(rq);
50         }
51 }
52
53 static void *loop()
54 {
55         struct json_object *rp;
56         struct async_request **tmp, **cur, *rq;
57
58         while (1) {
59                 log_debug("loop()");
60
61                 pthread_mutex_lock(&lock);
62                 if (requests) {
63                         tmp = requests;
64                         requests = NULL;
65                 } else {
66                         tmp = NULL;
67                 }
68                 pthread_mutex_unlock(&lock);
69
70                 if (tmp) {
71                         cur = tmp;
72                         while (*cur) {
73                                 rq = *cur;
74                                 rp = ws_execute(rq->request);
75
76                                 if (rq->callback)
77                                         rq->callback(rp, rq->data);
78
79                                 async_request_free(rq);
80                                 if (rp)
81                                         json_object_put(rp);
82
83                                 cur++;
84                                 usleep(100000);
85                         }
86                         free(tmp);
87                 }
88
89                 log_debug("loop() done");
90                 sleep(1);
91         }
92
93         pthread_exit(NULL);
94 }
95
96 static struct async_request *
97 add_async_request(struct json_object *rq,
98                   void (*callback)(struct json_object *, void *data),
99                   void *data)
100 {
101         struct async_request *async_rq;
102         struct async_request **tmp;
103
104         pthread_mutex_lock(&lock);
105         if (!thread) {
106                 thread = malloc(sizeof(pthread_t));
107                 pthread_create(thread, NULL, loop, NULL);
108         }
109         pthread_mutex_unlock(&lock);
110
111         async_rq = malloc(sizeof(struct async_request));
112         async_rq->request = rq;
113         async_rq->data = data;
114         async_rq->callback = callback;
115
116         pthread_mutex_lock(&lock);
117         tmp = (struct async_request **)list_add((void **)requests, async_rq);
118         list_free((void **)requests);
119         requests = tmp;
120         pthread_mutex_unlock(&lock);
121
122         return async_rq;
123 }
124
125 void ws_async_set_article_unread(int id, int unread)
126 {
127         struct json_object *rq;
128
129         log_debug("ws_async_set_article_unread(%d,%d)", id, unread);
130
131         rq = ws_request_new_set_article_unread(id, unread);
132
133         add_async_request(rq, NULL, NULL);
134
135         log_debug("ws_async_set_article_unread(%d,%d) done", id, unread);
136 }