New objects for GLib



Hi everyone,

In the course of developing the multithreaded ORBit I wrote two GLib objects,
that might be of general interest. The first one should in fact go into GLib,
as it offeres asyncronous communication between threads, which makes life much
more easy (and prevents everyone from reinventing the wheel). It is just a
small wrapper aroung GQueue, so it shouldn't be a size problem. The stripped
.o file is about 4K.

Here are the details for GAsyncQueue: (opaque datatype)
=============================================================================
/* Get and free GAsyncQueue */
GAsyncQueue*  g_async_queue_new                (void);
void          g_async_queue_free               (GAsyncQueue  *queue);

/* Lock and unlock an GAsyncQueue, all functions lock the queue for
 * themselves, but in certain cirumstances you want to hold the lock longer,
 * thus you lock the queue, call the *_unlocked functions and unlock it again
 */
void          g_async_queue_lock               (GAsyncQueue  *queue);
void          g_async_queue_unlock             (GAsyncQueue  *queue);

/* Push data into the async queue. Must not be NULL */
void          g_async_queue_push               (GAsyncQueue  *queue,
                                                gpointer      data);
void          g_async_queue_push_unlocked      (GAsyncQueue  *queue,
                                                gpointer      data);
/* Pop data from the async queue, when no data is there, the thread is blocked
 * until data arrives */
gpointer      g_async_queue_pop                (GAsyncQueue  *queue);
gpointer      g_async_queue_pop_unlocked       (GAsyncQueue  *queue);

/* Try to pop data, NULL is returned in case of empty queue */
gpointer      g_async_queue_try_pop            (GAsyncQueue  *queue);
gpointer      g_async_queue_try_pop_unlocked   (GAsyncQueue  *queue);

/* Wait for data until at maximum until end_time is reached, NULL is returned
 * in case of empty queue*/
gpointer      g_async_queue_timed_pop          (GAsyncQueue  *queue, 
                                                GTimeVal     *end_time);
gpointer      g_async_queue_timed_pop_unlocked (GAsyncQueue  *queue, 
                                                GTimeVal     *end_time);
/* Return the length of the queue, negative values mean, that threads are
 * waiting, positve values mean, that there are entries in the queue. Actually
 * this function returns the length of the queue minus the number of waiting
 * threads, g_async_queue_length==0 could also mean 1 entry in the queue and 1
 * thread waiting, such can happen due to locking of the queue or due to
 * scheduling.*/ 
gint          g_async_queue_length             (GAsyncQueue  *queue);
gint          g_async_queue_length_unlocked    (GAsyncQueue  *queue);
=============================================================================

The second datatype is a threadpool with automatic thread managment of GLib.
That means unused threads of one thread pool are assigned to other thread
pools, when needed there. To have such a thing inside a base lib is good,
because that way different libraries/applications (e.g. ORBit and GNOME and
the application) can use thread pools and still share the resources (the
threads).

The details are
=============================================================================
/* The real GThreadPool is bigger, so you can only get a thread pool with the
 * constructor function */

struct _GThreadPool
{
  GFunc thread_func;
  gulong stack_size;
  gboolean bound; 
  GThreadPriority priority;
  gboolean exclusive;
  gpointer user_data;
};

/* Get a thread pool with the function thread_func, at most max_threads may
 * run at a time (max_threads == -1 means no limit), stack_size, bound,
 * priority like in g_thread_create, exclusive == TRUE means, that the threads
 * shouldn't be shared and that they will be prestarted (otherwise they are
 * started, as needed) user_data is the 2nd argument to the thread_func */

GThreadPool*    g_thread_pool_new             (GFunc            thread_func,
                                               gint             max_threads,
                                               gulong           stack_size,
                                               gboolean         bound,
                                               GThreadPriority  priority,
                                               gboolean         exclusive,
                                               gpointer         user_data);

/* Push new data into the thread pool. This task is assigned to a thread later
 * (when the maximal number of threads is reached for that pool) or now
 * (otherwise). If necessary a new thread will be started. The function
 * returns immediatly */
void            g_thread_pool_push            (GThreadPool     *pool,
                                               gpointer         data);

/* Set the number of threads, which can run concurrently for that pool, -1
 * means no limit. 0 means has the effect, that the pool won't process
 * requests until the limit is set higher again */
void            g_thread_pool_set_max_threads (GThreadPool     *pool,
                                               gint             max_threads);

gint            g_thread_pool_get_max_threads (GThreadPool     *pool);

/* Get the number of threads assigned to that pool. This number doesn't
 * necessarily represent the number of working threads in that pool */
guint           g_thread_pool_get_num_threads (GThreadPool     *pool);

/* Get the number of unprocessed items in the pool */
guint           g_thread_pool_unprocessed     (GThreadPool     *pool);
/* Free the pool, immediate means, that all unprocessed items in the queue
 * wont be processed, wait means, that the function doesn't return immediatly,
 * but after all threads in the pool are ready processing items. immediate
 * does however not mean, that threads are killed. */
void            g_thread_pool_free            (GThreadPool     *pool,
                                               gboolean         immediate,
                                               gboolean         wait);
/* Set the maximal number of unused threads before threads will be stopped by
 * GLib, -1 means no limit */
void            g_thread_pool_set_max_unused_threads (gint      max_threads);
gint            g_thread_pool_get_max_unused_threads (void);
guint           g_thread_pool_get_num_unused_threads (void);
/* Stop all currently unused threads, but leave the limit untouched */
void            g_thread_pool_stop_unused_threads    (void);
=============================================================================

Hope for your comments,
Sebastian
-- 
Sebastian Wilhelmi                   |            här ovanför alla molnen
mailto:wilhelmi@ira.uka.de           |     är himmlen så förunderligt blå
http://goethe.ira.uka.de/~wilhelmi   |



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]