DMP Photo Booth: an Experimental GHashTable Transplant

DMP Photo Booth has had a problem; it has been battered by the club of poor design choices. Deep in the bowels of user_interface.c, there was a terrible cancer. There was a struct called dmp_pb_ui_cb_user_data that started life as an innocent little struct to be passed into GTK callbacks. Since the same pointer must be used for all callbacks to pass user data around, this was my solution. The only problem? Scalability.

At first, there was one member to worry about. One member to initialize, one member to free. Then there were 2. Then 4. Then 8. Things began to take a turn for the worse as my user data registration function ballooned to over 300 lines. Dozens of members to track, to new and destroy. Fearing that my poor user_interface.c file would end up on The Daily WTF I prepared for surgery. The cancer must go.

Easier said than done, right? It turns out, not so much.

GHashTable to the Rescue

Once again, GLib has the answer. After some thought, GLib’s Hash Table implementation offers the solution.

A hash table is a collection that associates a key with a value. You can pass in an integer, a string, or any other arbitrary type as a key, and get its associated value. In my case, I have ready-made keys: the Glade widget name. I can use these names as keys and associate them with their respective components as they are pulled out of the GtkBuilder. The filled hash can then be passed in as the user data pointer to gtk callbacks.

Let’s go over some of the details that make this is a good choice for DMP Photo Booth:

g_hash_table_new_full

This is, of course, the GHashTable constructor. Let’s examine an example, straight out of the new implementation:

dmp_pb_user_data = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify) gtk_widget_destroy );

This constructor takes 4 arguments: a hashing function, an equality function, a key destruction function, and a value destruction function. The hashing function is probably the most important of these. Hash tables generate a hash based on the key to find the value, this function implements the hash on a given type. GLib provides 3 ready-made hashing functions, g_str_hash (for char arrays), g_int_hash (for integers), and g_direct_hash (for void pointers). You can implement your own if you like, just make sure it’s fast. This function is called on all lookups, a slow hash function will destroy your program’s performance.

Next is the equality function. This function is used to test keys for equality.

Finally, we have the key and value destruction functions. These functions are responsible for ensuring memory is cleaned up. These functions will be called on destruction of the GHashTable, ensuring all memory is cleaned up properly. This is the reason we are using g_hash_table_new_full, and not g_hash_table_new. Without these functions, you have to manually empty the hash table and free all values if you want to avoid a memory leak.

g_hash_table_lookup

Next, is our lookup function. This function takes a pointer to a GHashTable, and a key. A pointer to the key’s value is returned, or NULL if the key does not exist. Pretty straight forward.

The Prognosis

Favorable. The new GHashTable is humming along, and dmp_pb_ui_register_user_data has shed hundred of lines. With a little diet and excercise, the patient should make a full recovery.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: