=== modified file 'includes/common.inc'
--- includes/common.inc	2009-12-06 17:01:52 +0000
+++ includes/common.inc	2009-12-07 07:32:43 +0000
@@ -3077,7 +3077,7 @@ function base_path() {
  * which on normal pages is up through the preprocess step of theme('html').
  * Adding a link will overwrite a prior link with the exact same 'rel' and
  * 'href' attributes.
- * 
+ *
  * @param $attributes
  *   Associative array of element attributes including 'href' and 'rel'.
  * @param $header
@@ -3477,7 +3477,7 @@ function drupal_load_stylesheet_content(
     $contents = preg_replace('{
       (?<=\\\\\*/)([^/\*]+/\*)([^\*/]+\*/)  # Add a backslash also at the end ie-mac hack comment, so the next pass will not touch it.
                                             # The added backshlash does not affect the effectiveness of the hack.
-      }x', '\1\\\\\2', $contents);    
+      }x', '\1\\\\\2', $contents);
     $contents = preg_replace('<
       \s*([@{}:;,]|\)\s|\s\()\s* |          # Remove whitespace around separators, but keep space around parentheses.
       /\*[^*\\\\]*\*+([^/*][^*]*\*+)*/ |    # Remove comments that are not CSS hacks.
@@ -5155,6 +5155,44 @@ function show(&$element) {
 }
 
 /**
+ * Prepare an element for caching based on a query.
+ *
+ * Expensive queries should use the query builder to create the query and then
+ * call this function. Executing the query and formatting results should happen
+ * in pre_render.
+ *
+ * @param $query
+ *   A select query object as returned by db_select().
+ * @param $function
+ *   The name of the function doing this caching. A _pre_render suffix will be
+ *   added to this string and is also part of the cache key in
+ *   drupal_render_cache_set() and drupal_render_cache_get().
+ * @param $expire
+ *   The cache expire time, passed eventually to cache_set().
+ * @param $granularity
+ *   One or more granularity constants passed to drupal_render_cid_parts().
+ *
+ * @return
+ *   A renderable array with the following keys and values:
+ *   - #query: The passed in $query.
+ *   - #pre_render: $function with a _pre_render suffix.
+ *   - #cache: An associative array prepared for drupal_render_cache_set().
+ */
+function drupal_render_cache_by_query($query, $function, $expire = CACHE_TEMPORARY, $granularity = NULL) {
+  $cache_keys = array_merge(array($function), drupal_render_cid_parts($granularity));
+  $query->preExecute();
+  $cache_keys[] = md5(serialize(array((string) $query, $query->getArguments())));
+  return array(
+    '#query' => $query,
+    '#pre_render' => array($function . '_pre_render'),
+    '#cache' => array(
+      'keys' => $cache_keys,
+      'expire' => $expire,
+    ),
+  );
+}
+
+/**
  * Get the rendered output of a renderable element from cache.
  *
  * @see drupal_render()

=== modified file 'modules/forum/forum.module'
--- modules/forum/forum.module	2009-12-04 16:49:45 +0000
+++ modules/forum/forum.module	2009-12-06 20:16:35 +0000
@@ -622,21 +622,9 @@ function forum_block_view($delta = '') {
       break;
   }
 
-  $cache_keys = array_merge(array('forum', $delta), drupal_render_cid_parts());
-  // Cache based on the altered query. Enables us to cache with node access enabled.
-  $query->preExecute();
-  $cache_keys[] = md5(serialize(array((string) $query, $query->getArguments())));
-
   $block['subject'] = $title;
-  $block['content'] = array(
-     '#access' => user_access('access content'),
-     '#pre_render' => array('forum_block_view_pre_render'),
-     '#cache' => array(
-        'keys' => $cache_keys,
-        'expire' => CACHE_TEMPORARY,
-     ),
-     '#query' => $query,
-  );
+  $block['content'] = drupal_render_cache_by_query($query, 'forum_block_view');
+  $block['content']['#access'] = user_access('access content');
   return $block;
 }
 

