I'm looking to write a multi-threaded application. As the GUI of this app will be written in GTK, and glib is getting dragged in anyways, I figured that I would use the glib threading abilities. Now, I understand that using a mutex is expensive compared to doing atomic reads an writes, an interesting ability provided by glib. So, wherever possible, I protected my data using atomic operations, and I've now reached the point where I have identified 8 points in my code that *must* use a mutex, It is here that I need some help.
Now, Glib provides a few Mutex-like abilities: GMutex, GStaticMutex, GLock, GStaticRecMutex, and GStaticRWLock. Now, from the documentation, I discover that GLock is just a convenience macro to GStaticMutex and GStaticRecMutex seems to just be a GStaticMutex with reference counting. So, I think my best bet is with GMutex, GStaticMutex, or GLock.
The trouble is, I'm unsure of the usage. For example, the glib documentation gives the following example code:
Code:
static GMutex *give_me_next_number_mutex = NULL;
/* this function must be called before any call to give_me_next_number ()
it must be called exactly once. */
void init_give_me_next_number ()
{
g_assert (give_me_next_number_mutex == NULL);
give_me_next_number_mutex = g_mutex_new ();
}
int give_me_next_number ()
{
static int current_number = 0;
int ret_val;
g_mutex_lock (give_me_next_number_mutex);
ret_val = current_number = calc_next_number (current_number);
g_mutex_unlock (give_me_next_number_mutex);
return ret_val;
}
So how do you tell g_mutex_new() what you want it to protect? Does it just protect everything in memory? Everything on this function's stack?
So then I moved onto GStaticMutex.
Code:
int give_me_next_number ()
{
static int current_number = 0;
int ret_val;
static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
g_static_mutex_lock (&mutex);
ret_val = current_number = calc_next_number (current_number);
g_static_mutex_unlock (&mutex);
return ret_val;
}
Same question here? How do I know what I'm protecting?
The GLock seems a bit better:
Code:
G_LOCK_DEFINE (current_number);
int give_me_next_number ()
{
static int current_number = 0;
int ret_val;
G_LOCK (current_number);
ret_val = current_number = calc_next_number (current_number);
G_UNLOCK (current_number);
return ret_val;
}
Here, I see current_number, but apparently, according to the documentation, whatever you put in is just mangled and used as the name, so them using current_number is just demonstrating that you can do so. Besides current_number isn't even defined when the G_LOCK_DEFINE runs.
So, is there any way to just lock one object? Does this mean you have to lock all of your functions stack at once?