Pretty much any system that requires a low-latency response to asynchronous events uses some form of callbacks, observers, or notifiers. They can be found in user interface toolkits, in which they are often called event listeners, and distributed systems. Callbacks are a generic mechanism allowing you to supply code that the system invokes when certain well-known events happen. They have a variety of forms, some making creative use of language-specific features. Languages like C, Perl, JavaScript, and others with a procedural or functional flavor use function pointers (Listing 12-6) or function references (Listing 12-7). Object-oriented languages often implement callbacks through implementations of special-purpose interfaces as in Listing 12-8. Languages with reflection or dynamic invocation capabilities can provide callback functionality through strings representing the names of classes, methods, or functions; Listing 12-9 shows an example using the Spring Scheduling framework. In some cases, operating systems present language-independent reflection-like mechanisms such as the POSIX dynamic-loading APIs (Listing 12-10). C++ pointer-to-member-function syntax (Listing 12-11) supports a kind of type-constrained callback. C++ function invocation operator overloading allows the use of function objects, or functors,6 as a form of callback as shown in Listing 12-12.
6. http://en.wikipedia.org/wiki/Function_object
#include <stdlib.h>
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
7. ISO/IEC 9899:1990 Section 7.10.5.2
$('.menu > .menuitem').each(function(index, element) {
console.log('Item ' + index + ' says ' + $(element).text());
});
public class HiThere implements ActionListener {
...
public void init() {
button.addActionListener(this);
}
...
public void actionPerformed(ActionEvent e) {
textArea.append("Hello, World!");
}
}
<bean id="runMeJob"
class="org.springframework.scheduling.quartz
.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="runMeTask" />
<property name="targetMethod" value="printMe" />
</bean>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
/* For NAN macro */
#define _GNU_SOURCE
#include <math.h>
double
call_double_return_double(char *libname,
char *funcname, double arg)
{
void *handle;
double (*func)(double);
char *error;
double result;
handle = dlopen(libname, RTLD_LAZY);
if (NULL == handle) {
fprintf(stderr, "%s
", dlerror());
return NAN;
}
dlerror(); /* Clear any existing error */
*(void **) (&func) = dlsym(handle, funcname);
error = dlerror();
if (error != NULL) {
fprintf(stderr, "%s
", error);
return NAN;
}
result = (*func)(arg));
dlclose(handle);
return result;
}
8. http://linux.die.net/man/3/dlopen
typedef double (Callback::*CallbackMember)(double);
call_double_returns_double(Callback &cb,
CallbackMember cbm, double arg)
{
return cb.*cbm(arg);
}
class AbstractFunctor
{
public:
virtual void operator()(const char *string)= 0;
}
9. ISO/IEC 14882:2011 Section 20.8
Specific uses of callbacks have become known by more specific names representing their particular purposes. The Observer pattern [DP] uses callbacks in a specialized way to immediately communicate when a particular state or condition changes. Another specialized form of callback, the notifier, allows client code to register interest in specific events, often as part of a logging or monitoring strategy.
All callbacks have the common purpose of synchronously communicating various conditions to interested code. Often the conditions that are the subject of the communication are otherwise encapsulated. For testing purposes, you should even consider the invocation of a callback as a feature requiring verification.
However, this feature of the code’s behavior also represents an exploitable seam. Callbacks usually accept data about the change or event that occurred. Callbacks also occur at well-understood times in the processing of the system that makes them available. More often than not, callbacks can be used to verify that the system handles and passes on data correctly, even when no other direct means is available. You can use mock implementations of callbacks for behavioral verification. You can even use them to exert control over test and thread execution, as we will see in Chapter 13.
3.141.28.107