- The Takeaway
- Getting the Picture
- A Callback Interface
- The C# Code
- Putting It All Together
- Callbacks Versus Delegates
- Conclusion
A Callback Interface
I want to equip my LSP type with the ability to inform us about its various state changes. Listing 2 illustrates the C# interface, which contains three members:
- GettingCongested()
- FullyCongested()
- CannotForwardData()
When you see the code, you'll understand these functions. For the moment, they merely reflect the state of the underlying LSP.
Listing 2 The Callback Interface
// The callback interface. public interface ILspStatus { void GettingCongested(string msg); void FullyCongested(string msg); void CannotForwardData(string msg); }
So, how does the LSP class use the callback interface? Listing 3 illustrates an excerpt from the Lsp class.
Listing 3 Part of the Lsp Class
public class Lsp { // The set of connected sinks. ArrayList clientSinks = new ArrayList(); // Attach to the event source. public void Attach(ILspStatus sink) { clientSinks.Add(sink); } // Detach from the event source. public void Detach(ILspStatus sink) { clientSinks.Remove(sink); }
To attach to and detach from the callback interface, the Lsp class provides two methods: Attach() and Detach().
So, you now have the callback interface in place and you know how to connect to and disconnect from it. The question remains: How do you implement the event mechanism? Listing 4 illustrates the implementation of the interface ILspStatus.
Listing 4 The Event Interface Implemented
public class LspEventSink : ILspStatus { private string name; public LspEventSink() {} public LspEventSink(string sinkName) { name = sinkName; } public void GettingCongested(string msg) { Console.WriteLine("{0} report: {1}", name, msg); } public void FullyCongested(string msg) { Console.WriteLine("{0} report: {1}", name, msg); } public void CannotForwardData(string msg) { Console.WriteLine("{0} report: {1}", name, msg); } }
As you can see from Listing 4, the object interested in using the callback mechanism does not typically implement callback interfaces. In the interests of separation of concerns and loose coupling, the callback mechanism is implemented as a "sink" entity. Notice in Listing 4 the definitions of the methods from Listing 2. It is the sink that is instantiated by the caller, as illustrated in Listing 5.
Listing 5 Instantiation of the Lsp and Event Sink Entities
// Instantiate an LSP Lsp lsp = new Lsp("LSP123", 1, 5, "R2R3R4R5", 100, 150); // Make sink object. Console.WriteLine("Creating LSP event sink\n"); LspEventSink sink = new LspEventSink("Event sink"); // Attach the sink to the LSP. Console.WriteLine("Attaching a sink to the LSP"); lsp.Attach(sink);
In Listing 5, I instantiate the event sink, and I also attach to it.
You are now set to receive events from the lsp object as it changes state! To get the ball rolling, I pass some traffic through the lsp object as illustrated by the call to lsp.ForwardSomeData() in Listing 6.
Listing 6 Changing the lsp State by Forwarding Traffic
// Forward some blocks of data (to generate some events.) Console.WriteLine("\n***** Forwarding data *****"); for (int i = 0; i < 3; i++) lsp.ForwardSomeData(20);
If at this stage I was using a non-callback style of programming, I'd have to check the state of some member data in the Lsp class. This is cumbersome and wastes resources. Isn't it much better if the lsp object tells me it has changed state? This is exactly what it does, thanks to the callback interface illustrated in Figure 2.

Figure 2 Attaching to the event sink and changing state.
In Figure 2, my lsp object is attached to the event sink, and I then forward some data. This causes the event to fire, indicating that congestion is imminent on LSP123. It also indicates the required bandwidth (120Mbps) versus the maximum allowed bandwidth (150Mbps).
What you're looking at in Figure 2 is in fact one of the hardest things to do in network management—getting an instantaneous view of the state of some critical resource (such as LSP123 in Figure 1). In many networks, you might never know that such a change has occurred until traffic starts to get dropped. In other networks, ongoing monitoring attempts to preempt the onset of congestion. But, such monitoring is often wasteful because much of the time the traffic level will be just fine.
The main problem with monitoring is that once the network starts to get overloaded, the monitoring function exacerbates the situation! The management starts to get in the way. So, if it's possible, the best solution is one where autonomous updates occur.