1
Concurrent design patterns for resource sharing Bo Sandén Colorado Technical University 4435 N. Chestnut Street Colorado Springs, CO 80907-3896
[email protected] (719) 590-6733 Fax: (719) 598-3740
1. Introduction Software design is traditionally regarded as a process issue and various stepwise methods are proposed. Design patterns allow a discussion of designs as such, without the process aspect. A pattern is a grouping of objects that is likely to be useful over and over. It describes a family of solutions to recurring problems. The standard reference [2] includes a catalog of 23 objectoriented patterns. (Further discussion in the full paper.) Like patterns, the entity-life modeling design approach for concurrent software (ELM) [5, 6, 8, 9] is concerned with the relationship between designs and problems. It encourages a restrictive use of concurrency where each task is justified by concurrency inherent in the problem. The model is that a real-time system must react to events in the problem environment. Each event is without duration but requires a finite processing time. The analyst's concern is to attribute these events to different concurrent threads. To do this, all events that the software must deal with are laid out along a time line in an imaginary trace, which is then partitioned the trace into threads. Each event belongs to exactly one thread and the events within each thread are separated by sufficient time for the processing of each event. Essentially, each thread is implemented as a task. (Complete description including pragmatics in the full paper.) Rather than going back to the first principles of ELM, a designer can use existing designs as models. It is useful to categorize these designs according to patterns. Patterns used in ELM include the State-machine [7] and a periodic pattern. Designs with resource conflicts follow a resource contention pattern [9]. (More in the full paper.) This paper concentrates on two patterns for sharing single resources: the assembly line and the single-resource pattern. An interesting duality exists in that either pattern may often be used in a given problem.
2. Resource sharing patterns A simple data-entry application [1] illustrates the assembly line and single-resource patterns. The application prompts an operator to input 100 numeric sales figures into a buffer. It then uses those values to update a revenue spreadsheet on disk. After the updating, the operator is again prompted for input. If this is done sequentially, the operator suffers a delay after the first values have been entered and before she can continue typing. We can use multi-tasking to overlap the data entry and the file processing. To find thread models, consider events of the types: user presses enter and disk access completes. The user presses enter events form one thread, Data_Entry, and all disk access com-
04/10/97
2
pletes form another, Updating. The solution with the two tasks Data_Entry and Updating is a small example of the assembly-line pattern with two stations, connected by a queue of buffers. Alternatively, let all the events that happen to a set of input data be a thread. This leads to a solution with a task type Enter_and_Update that repeatedly first accepts the operator input, then updates the spreadsheet. We can have 2 (or more) instances of Enter_and_Update. This solution is according to the single-resource pattern. Each task instance needs exclusive access first to an Operator resource, then to a File resource. We represent each resource as a protected unit with an Acquire entry and a Release procedure. The assembly line and single-resource patterns are also known as function partitioning and data partitioning, respectively. In the following we first discuss each pattern separately with a number of examples, then cases where the designer has a choice.
3. Assembly-line pattern In the assembly-line pattern, parts flow between handling stations of some kind. Each station can handle one part at a time. In some systems, a physical assembly line ensures the mutual exclusion and queuing of parts. In other examples, the “parts” are data packets that undergo transformations by software. In these cases, the software must ensure that the order of the parts is not changed unintentionally and provide for the necessary queuing. An example of this nature is the MIDI patch bay problem discussed below. With physical assembly lines, a solution with one task per part is usually inconvenient since tasks would continuously be created and destroyed as parts enter and leave the assembly line.
3.1 Baggage handling system In a baggage control system, the stations are way-points where luggage may be routed off the main conveyor onto a baggage pick-up or loading area, or vice versa [8]. Whenever a luggage item arrives at a station, its identity is established from a bar code and a routing decision is made. One portion of the baggage handling system is an unloading station. Each piece of luggage travels on a cart. A destination sensor on the main track determines the identity of each approaching cart. If necessary, the cart is switched into an unloading siding, where it first enters a deceleration ramp. At the end of the ramp, there is an unload queue of carts waiting to be unloaded. The unloading machinery unloads each cart in order, then places it in a merge queue of empties to be merged back onto the main track. A merge sensor on the main track is used to detect a gap in traffic on the main track that may allow an empty cart to enter. The cart accelerates along an acceleration ramp onto the main track. The physical assembly line is mirrored in the software: The task Cart_Arrival repeatedly accepts an interrupt from the destination sensor and switches carts onto the deceleration ramp.
04/10/97
3
The protected unit Unload_Queue holds the number of carts in the unload queue. The task Unloader pends on the unload queue. When a cart is available, Unloader takes it through the steps of unloading, then moves it to the merge queue. Unloader calls Merge_Queue.Insert and makes a conditional call to the Incoming_Cart entry of task Merger. The task Merger launches carts form the merge queue when the exclusion zone is free as indicated by the time expired since the last cart passed the merge sensor. (A diagram of the design, a state transition diagram and the task body of Merger are in the full paper. They show that the design itself resembles an assembly line.) 3.2 LEGO car factory If there is no buffering, the stations hand over parts to each other. The stations operate concurrently on each part, but are synchronized pair-wise during the hand-over. In [8, 10] a toy factory of LEGO cars is described, which is itself constructed from LEGO parts. The products are put together in an assembly line consisting of the following: (The layout is shown in the full paper.) A store of bottom parts and a pusher that pushes bottoms onto the conveyor. A store of chassis parts with a pusher that pushes the pieces onto a bottom. An optical sensor detects when the store is empty. To control the position of a bottom on the conveyor there is a mechanical stop and a photo cell. The optical sensor only indicates the presence of a bottom, while the stop ensures that the bottom is placed in the exact right position for the placement of the chassis parts. etc. As can be seen in the design diagram (in the full paper), a Bottoms task, a Chassis task, etc., form an assembly line. Protected units are used to remember interrupts for later reference. For example, an interrupt is generated when the last bottom piece is removed from the store. The Bottoms task can later call an entry Store_Filled and be queued until the store is no longer empty.
3.3 Data-transfer applications A different example of the assembly-line pattern is when the software receives a stream of messages and transforms each message in one or more steps. There may be multiple input and output channels. Order preservation and throughput are usually primary concerns. With several conversion steps and particularly with several processors, it is desirable to set up as assembly line of task that successively convert each incoming message.
04/10/97
4
The example to be used here is a MIDI patch bay. MIDI (Musical Instrument Digital Interface) is a message protocol for communication between musical instrument controllers and other electronic units. Each message consists of a status byte followed by 0 - 2 data bytes. (Further discussion in the full paper.) A programmable patch bay consists of a number of input and output ports. In addition to forwarding messages to any or all output ports, each input port can also translate or suppress messages with certain status bytes, etc. The patch-bay design is according to the assembly-line pattern. Protected units are used to handle the input and output devices: The protected type Port_Input hides a buffer of input bytes. It provides a handler for the input interrupt and an entry that allows the task Port to retrieve the next byte or be queued until a byte is available. The task Port pends for a byte on the appropriate Port_Input object and performs any necessary translation and transposition. It calls the appropriate Port_Output object and inserts the message into the buffer. The protected type Port_Output hides a buffer of output bytes. It provides: a procedure allowing a byte to be inserted. an entry that yields the byte at the head of the queue. The task Asynch_Output pends on Port_Output until a byte needs to be transmitted, then performs the transmission. (Additional complications as discussed in the full paper.)
4. The Shared-Resource pattern The situation where two or more resource users need exclusive access to a shared resource is a classic problem in concurrency. Complications include cases where there is a pool of resources from which each user needs one. The challenge is often to recognize that a problem can be cast in terms of resource users and shared resources. This is illustrated by the following example.
4.1 Home-heating system A home-heating system maintains a preset reference temperature in a group of 5 homes. The heating cycle for each home involves several specific waits to allow the heater motor to rev up, etc. [3]. The homes share a fuel tank and for capacity reasons, only 4 homes may be heated simultaneously. Each home may be forcibly without heat for no more than 10 minutes.
04/10/97
5
The constraints introduce an element of resource contention. A pool of 4 heating “tokens” are implemented in a protected unit. Before starting the heater, a Home task first obtains a token by calling Acquire. If no token is obtained immediately, the home tries again for up to 10 minutes, then demands a token by calling Insist, and is given one even at the price of shutting off the heat in another home. A home determines the need to shut off its own heating for the benefit of another home by periodically querying the value of a variable that serves as a logical on/off switch.
5. Comparison of patterns In some problems, both an assembly-line and a single-resource solution are possible. The choice sometimes leads to interesting differences as in the following example:
5.1 The remote temperature sensor problem The Remote Temperature Sensor (RTS) periodically senses the temperature of 16 furnaces. It is connected to an A/D converter that multiplexes between thermocouples connected to each furnace. The RTS sends each temperature reading as a data packet (DP) to a host computer. Each furnace is monitored with its own frequency, which is subject to change by means of a control packet (CP) from the host. The RTS problem was first presented in [11]. A design based on data flow is described in [4]. In a single-resource solution [5, 6], 16 periodic tasks of type Furnace sample the furnaces and send the DPs. The thermometer and the output line are shared resources. Each sampler makes a delay commensurate with its current sampling frequency. The delay must be broken when a CP arrives. The task Input receives the CPs and calls a Furnace task when its frequency is changed. Furnace waits for this call during its delay. The call is conditional, since Furnace cannot always accept it immediately. (See full paper and [7] for details.) The single-resource solution has the advantage that it directly uses the Ada run-time system to schedule the temperature readings. The need to change the periodicity complicates this otherwise straight-forward solution. In an assembly-line solution, temperature readings flow between two tasks: Temp_Sampler that does all the sampling, and Output that takes readings from a queue and sends the DPs. Temp_Sampler keeps a table with the next reading time for each furnace. This solution simplifies the handling of CPs considerably. The only design concern is the possible overflow of the queue in case the line goes down and messages cannot be sent.
6. Conclusion The cited examples and others indicate that the assembly-line pattern often leads to simpler solutions than the single-resource pattern. The single-resource pattern should be considered if the resource users are already implemented as tasks. This is the case in the home-heating
04/10/97
6
system, where the home tasks perform periodic sampling of the room temperature, etc. (It is also the case in the RTS, where, however, the situation is complicated by the handling of incoming control packets.) In other examples, the resource user tasks may sustain dialogs with human operators. In general, it may not be necessary to stipulate when one or the other pattern should be used. The existence of the two patterns should make a designer aware of the resource-sharing situation and prompt a deliberation of which pattern is preferable in a given problem.
References 1. R. R. Asche, Multithreading for rookies, Microsoft Development Library, September 1993. 2. E. Gamma, R. Helm, R. Johnson, J. Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley 1995 3. D. Hatley and I. A. Pirbhai. Strategies for Real-Time System Specification. Dorset House, 1987. 4. K. W. Nielsen and K. Shumate. Designing large real-time systems with Ada. Communications of the ACM , 30(8):695-715, August 1987. Corrected in CACM 30:12, December 1987, 1073 5. B. I. Sanden. Entity-life modeling and structured analysis in real-time software design - a comparison. Communications of the ACM , 32(12):1458-1466, December 1989. 6. B. I. Sanden. Software Systems Construction with Examples in Ada. Prentice-Hall, 1994. 7. B. I. Sandén. The State Machine pattern. Proc. TRI-Ada, Philadelphia, PA, Dec. 1996, 135 142. 8. B. I. Sandén. A course in real-time software design based on Ada 95, Available through the ASSET repository as ASSET_A_825, 1996 9. B. I. Sandén. Design of concurrent software based on problem concurrency. To appear in IEEE Software 1997. 10. J.-E. Strömberg. Styrning av LEGO-bilfabrik. Laboration i digital styrning. Linköpings Tekniska Högskola, 1991. 11. S. J. Young. Real-time Languages: Design and Development, Ellis Horwood, Chichester, West Sussex, England 1982
dualabstract 1997-04-09
04/10/97