Add to git.
[monolith.git] / chat / thread.c
1 /* Monolith chat ping thread.
2  * - by Richard W.M. Jones <rich@annexia.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * $Id: thread.c,v 1.4 2003/02/22 12:56:27 rich Exp $
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include <pool.h>
27 #include <pthr_pseudothread.h>
28
29 #include <monolith.h>
30
31 #include "chatroom.h"
32
33 /* This is the chat ping thread. This thread sends out a blank message
34  * to all rooms at a periodic interval. The reason for having this thread
35  * at all is to stop proxy servers and browsers from timing out the
36  * connection to the chat server. The blank message just ensures that some
37  * more data is sent over the TCP connection.
38  *
39  * This thread also serves another useful purpose: if we lose the connection
40  * to the user because of a network failure, then the blank message will
41  * detect this too.
42  *
43  * This thread starts up as soon as the chat library (ie. libmonolithchat.so)
44  * is loaded. We take care to kill the thread if the chat library is
45  * unloaded. Because there is no way to explicitly kill a thread, we
46  * have to set a 'quit' flag, and rely on the thread reading this flag
47  * and exiting itself. There is an added complication here however. The
48  * 'quit' flag itself cannot be allocated in static memory, because this
49  * memory would be unmapped by the time the chat thread gets round to
50  * reading it. So instead we allocate a byte in global_pool for this flag.
51  */
52
53 static void chat_ping_thread_init (void) __attribute__((constructor));
54 static void chat_ping_thread_stop (void) __attribute__((destructor));
55 static void run (void *);
56
57 static pool thread_pool = 0;
58 static pseudothread pth;
59 static unsigned char *quit_ptr; /* Address of the quit flag (see above). */
60
61 #define INTERVAL 120            /* Seconds between messages. */
62
63 static void
64 chat_ping_thread_init ()
65 {
66   if (thread_pool) abort ();    /* Something very wrong has happened. */
67
68   /* Allocate memory for the quit flag from global_pool - not statically
69    * because the memory would become unmapped before the thread would have
70    * a chance to read it.
71    */
72   quit_ptr = pmalloc (global_pool, sizeof (unsigned char));
73   *quit_ptr = 0;
74
75   /* Create and start up the thread. */
76   thread_pool = new_pool ();
77   pth = new_pseudothread (thread_pool, run, quit_ptr, "chat ping thread");
78   pth_start (pth);
79 }
80
81 static void
82 chat_ping_thread_stop ()
83 {
84   *quit_ptr = 1;
85 }
86
87 static void
88 run (void *vp)
89 {
90   unsigned char *quit_ptr = (unsigned char *) vp;
91
92   for (;;)
93     {
94       pth_sleep (INTERVAL);
95       if (*quit_ptr) return;
96       chatroom_spam_blank (thread_pool);
97     }
98 }