src/mn-reentrant-mailbox.gob (3156B) - raw
1 /*
2 * Mail Notification
3 * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 %headertop{
21 #include "mn-mailbox.h"
22 %}
23
24 %{
25 #include <gtk/gtk.h>
26 #include "mn-mailbox-private.h"
27 #include "mn-util.h"
28
29 typedef struct
30 {
31 MNReentrantMailbox *self;
32 int check_id;
33 } CheckInfo;
34 %}
35
36 class MN:Reentrant:Mailbox from MN:Mailbox (abstract)
37 {
38 private unsigned int queue_check_id;
39
40 private int check_id;
41 private int check_unique_id;
42
43 override (MN:Mailbox) void
44 removed (MNMailbox *mailbox)
45 {
46 Self *self = SELF(mailbox);
47
48 PARENT_HANDLER(mailbox);
49
50 /* abort the current check */
51 g_atomic_int_set(&selfp->check_id, 0);
52 }
53
54 finalize (self)
55 {
56 if (selfp->queue_check_id)
57 g_source_remove(selfp->queue_check_id);
58 }
59
60 /**
61 * queue_check():
62 * @self: a mailbox
63 *
64 * Queues a mail check on @self, or replaces an already queued check.
65 *
66 * This function is not thread-safe. It is only called from main
67 * loop callbacks (hence always from the same thread).
68 **/
69 protected void
70 queue_check (self)
71 {
72 if (! selfp->queue_check_id)
73 selfp->queue_check_id = gdk_threads_add_idle(self_queue_check_cb, self);
74 }
75
76 private gboolean
77 queue_check_cb (gpointer data)
78 {
79 Self *self = data;
80
81 mn_mailbox_check(MN_MAILBOX(self));
82
83 selfp->queue_check_id = 0;
84 return FALSE; /* remove source */
85 }
86
87 override (MN:Mailbox) void
88 check (MNMailbox *mailbox)
89 {
90 Self *self = SELF(mailbox);
91 CheckInfo *info;
92
93 PARENT_HANDLER(mailbox);
94
95 mn_mailbox_set_error(mailbox, NULL);
96
97 if (++selfp->check_unique_id == 0)
98 ++selfp->check_unique_id;
99
100 info = g_new(CheckInfo, 1);
101 info->self = g_object_ref(self);
102 info->check_id = selfp->check_unique_id;
103
104 g_atomic_int_set(&selfp->check_id, info->check_id);
105
106 mn_thread_create((GThreadFunc) self_check_thread_cb, info);
107 }
108
109 private void
110 check_thread_cb (CheckInfo *info)
111 {
112 Self *self = info->self;
113
114 self_reentrant_check(self, info->check_id);
115
116 g_atomic_int_compare_and_exchange(&selfp->check_id, info->check_id, 0);
117
118 GDK_THREADS_ENTER();
119
120 g_object_unref(self);
121
122 gdk_flush();
123 GDK_THREADS_LEAVE();
124
125 g_free(info);
126 }
127
128 virtual private void
129 reentrant_check (self, int check_id (check != 0));
130
131 protected gboolean
132 check_aborted (self, int check_id (check != 0))
133 {
134 return g_atomic_int_get(&selfp->check_id) != check_id;
135 }
136 }