Passing a function to another function?Recently I wrote an article about how I handled semaphores in a Drupal project. I want to talk about how I actually implemented it. I needed more than one function to use the semaphore. The goal was to prevent one function to be called when the semaphore was active. The semaphore would get activated when the function would run. Basically, prevent the functions from running at the same time. These functions were doing some hard work that could take 2-30 minutes. Having 6 (or more) of them running at the same time was slowing down the server. So the semaphore is to prevent the server from crashing but allow these functions to be executed. I created a function like this: /** * Wrapper that prevent a function from being called in paralell. * This is meant for functions that takes a lot of time to run and * cannot be run when another process already runs it. * This is because if the project takes a lot of time to run * and cron tried to start a new one, we do not want the * server to crash. This prevent the second call to run if * the first one is not finished. * * Here is an example on how to use it. * project_wrap_semaphore('print', array('Hello World')); * * @param $callback * Function name to be called only once at a time. * @param $args * Arguments for the callback function. */ function project_wrap_semaphore($callback, $args = array()) { $semaphore = variable_get('project_semaphore', FALSE); if ($semaphore) { if ((time() - $semaphore) <= (3600*3)) { // project is still running normally. watchdog('project', t('Attempting to re-run project while it is already running.'), WATCHDOG_WARNING); return; } // Either project has been running for more than 3 hours or the semaphore // was not reset due to a database error. watchdog('project', t('project has been running for more than 3 hours and is most likely stuck.'), WATCHDOG_ERROR); // Release project semaphore variable_del('project_semaphore'); } // Register shutdown callback register_shutdown_function('drupal_project_cleanup'); // Lock project semaphore variable_set('project_semaphore', time()); call_user_func_array($callback, $args); // Record project time variable_set('project_last', time()); watchdog('project', t('project run completed.'), WATCHDOG_NOTICE); // Release project semaphore variable_del('project_semaphore'); // Return TRUE so other functions can check if it did run successfully return TRUE; } /** * Shutdown function for project cleanup. */ function drupal_project_cleanup() { // See if the semaphore is still locked. if (variable_get('project_semaphore', FALSE)) { watchdog('project', t('project run exceeded the time limit and was aborted.'), WATCHDOG_WARNING); // Release project semaphore variable_del('project_semaphore'); } } You will notice that the first thing you might find odd about this function is that it receives a callback as a parameters. You need to pass the name of a function to execute. This callback/function will get called only if the semaphore does not exists. This means you do not know in advance which function will be called since that is dynamic. This is not a new concept. PHP already does that in a number of functions. Here's some PHP functions just to name a few: There is much more. I think that is totally natural to have functions that accepts functions as parameters. What do you think?
|
SearchDrupal ContributionsMake a Payment to Christian Roy |
Post new comment