mail-notification

Fork of Jean-Yves Lefort's mail-notification, a tray icon to notify of new mail
git clone https://code.djc.id.au/git/mail-notification/

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 }