11.6 Framework Classes Components for Concurrency

11.6 Framework Classes Components for Concurrency

A framework is a class or collection of classes that has a predefined structure and represents a generalized pattern of work. In the same manner that programs provide general solutions to specific problems, frameworks provide specific solutions to classes of problems. That is, an application framework captures the general flow of control for an entire range of programs that all solve or represent problems in a similar fashion. Put another way, an application framework represents a single solution to a family of problems. Frameworks are generic mini self-contained applications. The framework serves as a blueprint for the mini-application. It embodies the fundamental structure or skeleton that the application will have without providing the application details. The framework class specifies the relationships, responsibilities, patterns of work, and protocols between software parts in an object-oriented architecture without providing the implementation details. For instance, we can design a language processor class that captures the general pattern of work for an entire range of applications. The specific pattern of work that the language processor captures is the work involved in taking some input language and translating that language to some output form. This framework consists of a few common software parts:

  • Validation components

  • Tokenizer components

  • Parser components

  • Syntax analysis components

  • Lexical analysis components

These software parts can be combined to form a very familiar pattern of work:

Example 11.24 Declarations for the language_processor class and definition for the process_input method.
 class language_processor {    //... protected:    virtual bool getString(void) = 0;    virtual bool validateString(void) = 0;    virtual bool parseString(void) = 0;    //... public:    bool process_input(void); }; bool language_processor::process_input(void) {    getString();    validateString();    parseString();    //...    compareTokens();    //... } 

First, the language_processor class is an abstract base class because it contains pure virtual functions:

 virtual bool getString(void) = 0; virtual bool validateString(void) = 0; virtual bool parseString(void) = 0; 

This means it is not meant to be used directly. It serves as a blueprint for derived classes. The other important thing to note is the process_input() method. This method captures the general pattern of work that the language_processor class is meant to generalize. In many ways this is what distinguishes framework classes from other types of classes. The framework not only contains generalized structure and relationships between components, it also captures predefined patterns of work and sequences of action. It provides the skeleton for the pattern of work without providing the implementation details. In this case, the pattern of work is specified by a set of pure virtual functions. So the framework class does not specify how these things are to be done ”it only specifies that they should be done and they should be done in a certain order. The derived class has to provide the implementations for the pure virtual functions. The framework class emphasizes the responsibilities of the derived class. Framework classes by definition are contract classes. They require two parties in order to work properly. The framework class does its part but the derived class must provide the implementation details for the pure virtual functions. The commonly found sequence of actions performed by the process_input() method are found in:

Compilers

Command interpreters

Natural language processors

Encryption/decryption routines

Compression/ decompression

File transfer protocols

Graphical user interfaces

Device control, etc.

So by properly designing the language_processsor class, the pattern of work for an entire range of applications is captured. If the sequence can be properly recorded and tested and debugged , then a wide range of applications can be developed faster by reusing the language_processor framework class.

The notion of a framework class is also useful in developing applications that have concurrency requirements. Specifically, the use of agent frameworks and blackboard frameworks captures the basic structure of concurrency and patterns of work within those structures. Michael Wooldridge, in Reasoning About Rational Agents , gives us a generalized agent control loop:

 Algorithm: Agent control Loop B = B0 while true do   get next percept p   B = brf(B,p)   I = deliberate(B)  P  = plan(B,I)   execute(  P  ) end while 

This pattern of work is performed by a wide range of rational agents. If you are developing a program that uses rational agents, then the chances are good that this sequence of actions will be found in your program. This is exactly the type of sequence of action that frameworks are good at capturing. For the agent control loop, the brf() , deliberate() , plan() functions will be pure abstract virtual. The agent control loop specifies what order these functions should be called and how they should be called, and the fact that they should be called. However, what the functions actually do will be determined by a derived class. Once this agent control loop is properly defined, then an entire class of problems has been solved . It turns out that systems consisting of multiple agents executing concurrently are becoming a standard for implementing parallel programming applications. These systems are often called multiagent systems. We discuss agent-oriented architectures in Chapter 12. It is important to note that agent framework classes help to reduce the complexity of developing multiagent systems and multiagent systems are becoming the preferred architecture for implementing medium- to large-scale applications that require concurrency or massive parallelism.

In addition to providing the pattern of work that will be useful for parallel or distributed systems, the framework class can capture the structure with respect to synchronization components such as object-oriented mutexes , semaphores, and message streams. The blackboard stucture is a useful medium for multiple agents to communicate through. The blackboard will be a critical region because multiple agents will be able to read and write to it simultaneously . Therefore, the framework class should provide the basic structure for the relationships between the agents, the synchronization components, and the blackboard. For instance, Example 11.25 contains two methods that the framework could use to access the blackboard.

Example 11.25 Definition of recordMessge() and getMessage() methods for the agent_framework class.
 int agent_framework::recordMessage(void) {    Mutex.lock();    BlackBoardStream << Agent[N].message();    Mutex.unlock(); } int agent_framework::getMessage(void) {    Mutex.lock();    BlackBoardStream >> Values;    Agent[N].perceive(Values);    Mutex.unlock(); } 

Here the framework class will protect the access to the blackboard by using synchronization objects. So when agents read messages from or write messages to the blackboard, the synchronization is already provided by the framework. The programmer does not have to worry about synchronizing blackboard access. Figure 11-11 contains the basic structure of our agent framework and how the framework relates to a blackboard.

Figure 11-11. The basic structure of the agent_framework class and how it relates to the blackboard.

graphics/11fig11.gif

Notice that the framework encapsulates the object-oriented mutexes and condition variables . The agent framework in Figure 11-11 will use either MPI or PVM message streams to communicate in a MPI- or PVM-based system. Recall these message streams were designed as interface classes and allow the programmer to use the iostream metaphor to access the PVM or MPI class. If MPI or PVM are not used, the agents can communicate using sockets, pipes, or even shared memory. In either case, we recommend that the synchronization primitives be implemented using interface classes since that will make them simpler to use. The blackboard in Figure 11-11 is object-oriented and takes advantage of the genericity provided by template classes. This also simplifies the concurrency requirements. The agents executing concurrently provide an effective model for parallel and distributed programming.



Parallel and Distributed Programming Using C++
Parallel and Distributed Programming Using C++
ISBN: 0131013769
EAN: 2147483647
Year: 2002
Pages: 133

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net