Title: Reading C2-style Applications Built in c2.fw
1Reading C2-style Applications Built in c2.fw
- Eric M. Dashofy
- edashofy_at_ics.uci.edu
- For ICS 52
- October 20, 2004
2Overview
- Software architectures
- The C2 architectural style
- With live example
- The Klax application
3Software Architecture Basic Elements
Interfaces
Clock
Component
Connector
Bus1
Interfaces
4Software Architecture Basic Elements (cont).
Clock
Configuration
Links
Bus1
LCD Driver
5An Architectural Style
- One definition of an architectural style
- An architectural style is a named set of
constraints (e.g., rules) you put on your
development - Constraints may be topological, behavioral,
communication-oriented, you name it - This can complicate development because these
constraints may be inconvenient or unfamiliar - BUT architectural styles elicit beneficial system
properties that would be really hard to get
otherwise
6Examples from building architecture
- Name some constraints in each style
- Name some benefits (-ilities) elicited by each
style.
7The C2 Architectural Style
- Topological Constraints
- All components, connectors have two interfaces,
top and bottom - Components can be connected to 0-1 connector on
each interface - Connectors can be connected to 0 components or
connectors on each interface
8The C2 Architectural Style
- Communication Constraints
- Components connectors communicate using only
independent events or messages - Requests go up (requests rise)
- Notifications go down
- No passing pointers
- Components connectors communicate
asynchronously - Can send/receive events at any time
- No blocking!
9The C2 Architectural Style
- Dependency Constraints
- Components may make assumptions about services
provided above them - But not who is providing them
- Components may NOT make assumptions about
services provided below them - Concurrency Constraints
- Each component connector assumes its running
in its own thread of control
10Live Example
Data Store
GUI Interpreter
Alarm
GUI
11Live Example
Data Store
Stores data emits notifications whenever data
changes.
GUI Interpreter
Alarm
GUI
12Live Example
Interprets basic GUI actions translates them
into data store operations
Data Store
GUI Interpreter
Alarm
GUI
13Live Example
Data Store
Rings a bell whenever value of X changes
GUI Interpreter
Alarm
GUI
14Live Example
Data Store
GUI Interpreter
Alarm
Accept process user actions
GUI
15Live Example
Data Store
GUI Interpreter
Alarm
Bus connector routes messages
GUI
16Live Example
Data Store
GUI Interpreter
Alarm
GUI
17What ilities does C2 buy us?
18-ilities bought by C2
- Flexibility
- Loose coupling lets you swap out components,
interpose components - Flexible connectors allow run-time changes
- Distributability
- Since no assumption of shared address space,
distributing an app across machines is easy - Visibility
- Since all messages go through connectors, they
are easy to catch and log - Parallelizability
- One-thread-per-brick means multiprocessor
machines are effectively utilized
19Event-based vs. OO
- Event-based
- Communication by events
- Mostly asynchronous
- Requests emitted to unknown parties
- Responses and state changes go to many parties
- No shared pointers
- Object Oriented
- Communication by procedure calls
- Mostly synchronous
- Requests emitted to named party only
- Responses to caller only, state changes to many
- Lots of shared pointers
20Implementing a C2 architecture
C2 architecture
Event-basedWorld
Implemented by
Application (implemented)
???
How do we bridge this gap?
Java/JVM
Object-orientedWorld
Uses services provided by
Native OS
21Implementing a C2 architecture
C2 architecture
Event-basedWorld
Implemented by
Application (implemented)
Uses services provided by
Architecture Framework
Uses services provided by
Java/JVM
Object-orientedWorld
Uses services provided by
Native OS
22Whats an architecture framework?
- An architecture framework is software that helps
to bridge the gaps between an architectural style
and a particular implementation platform.
23Example
- C2 World
- Components
- Connectors
- Events
- Links
- Many threads
- Asynchronous communication
- Java World
- Objects
- Method calls
- Parameters
- References
- Few threads
- Synchronous communication
24Enter c2.fw
- c2.fw is an architecture framework for the C2
style built in Java, providing - Abstract base classes for components, connectors
- Reusable connectors (local network)
- (Pluggable) topology management
- (Pluggable) message queuing policies
- (Pluggable) threading policies
- Essentially, c2.fw does the hard work, components
and connectors simply implement behaviors.
25What does a message look like?
- In c2.fw, a message can be any serializable (e.g.
no pointers) object - NamedPropertyMessages (or subclasses) are popular
though - Have a String name
- Plus a set of name-value pairs
- e.g. description, Rectangle 1
- e.g. width, 123
- e.g. color, java.awt.Color.BLACK
26Reading a c2.fw application
- Basic format
- Lifecycle methods
- init(), begin(), end(), destroy()
- start(), stop(), suspend(), resume()
- Handling messages
- void handle(Message m)
- Sending messages
- sendToAll(Message m, Interface i)
27Your basic c2.fw component
package edu.uci.ics.mypackageimport c2.fw.
//import c2.fw packageimport c2.legacy.
//import support for 2-interface
//C2 components
28Your basic c2.fw component
package edu.uci.ics.mypackageimport c2.fw.
//import c2.fw packageimport c2.legacy.
//import support for 2-interface
//C2 componentspublic class MyC2Component
extends AbstractC2Brick
Implements lots of boilerplate functionality from
the base c2.fw.Brick interface declares a top
interface topIface and a bottom interface
bottomIface.
29A boilerplate c2.fw component
package edu.uci.ics.mypackageimport c2.fw.
//import c2.fw packageimport c2.legacy.
//import support for 2-interface
//C2 componentspublic class MyC2Component
extends AbstractC2Brick public
MyC2Component(Identifier id) super(id)
Each component or connector has a unique
identifier.
30A boilerplate c2.fw component
package edu.uci.ics.mypackageimport c2.fw.
//import c2.fw packageimport c2.legacy.
//import support for 2-interface
//C2 componentspublic class MyC2Component
extends AbstractC2Brick public
MyC2Component(Identifier id) super(id)
public void begin() //called automatically
by fw. //send out initial events
31Lifecycle Methods
public void init() //called when
component/connector is created //but component
not guaranteed to be hooked up public void
begin() //called when component/connector is
hooked up //in the architecture, should send
initial messages public void end() //called
when component/connector is about to be
//unhooked, should send final messages public
void destroy() //called when
component/connector is about to be //destroyed
32A boilerplate c2.fw component
package edu.uci.ics.mypackageimport c2.fw.
//import c2.fw packageimport c2.legacy.
//import support for 2-interface
//C2 componentspublic class MyC2Component
extends AbstractC2Brick public
MyC2Component(Identifier id) super(id)
public void begin() //called automatically
by fw. //send out initial events
public void handle(Message m) //handle
message
33Implementing handle()
//handle() method for our hypothetical alarm
component //Called automatically when component
receives a message //Should ring bell whenever
value of X changes public void
handle(Message m) //handle message
34Implementing handle()
//handle() method for our hypothetical alarm
component public void handle(Message m)
//handle message if(m instanceof
NamedPropertyMessage) NamedPropertyMessage
npm (NamedPropertyMessage)m
35Implementing handle()
//handle() method for our hypothetical alarm
component public void handle(Message m)
//handle message if(m instanceof
NamedPropertyMessage) NamedPropertyMessage
npm (NamedPropertyMessage)m String name
npm.getName() if((name ! null)
(name.equals(valueChanged))
36Implementing handle()
//handle() method for our hypothetical alarm
component public void handle(Message m)
//handle message if(m instanceof
NamedPropertyMessage) NamedPropertyMessage
npm (NamedPropertyMessage)m String name
npm.getName() if((name ! null)
(name.equals(valueChanged)) String
varName (String)npm.getParameter(varName)
if((varName ! null) (varName.equals(x))
37Implementing handle()
//handle() method for our hypothetical alarm
component public void handle(Message m)
//handle message if(m instanceof
NamedPropertyMessage) NamedPropertyMessage
npm (NamedPropertyMessage)m String name
npm.getName() if((name ! null)
(name.equals(valueChanged)) String
varName (String)npm.getParameter(varName)
if((varName ! null) (varName.equals(x))
ringBell()
NamedPropertyMessage rnpm new
NamedPropertyMessage(AlarmFired)
rnpm.addProperty(time,
System.currentTimeMillis())
sendToAll(rnpm, bottomIface)
38Implementing handle()
If we care, we could have checked what interface
that message came in on if(m.getDestination().g
etInterfaceIdentifier().equals(
AbstractC2Brick.TOP_INTERFACE_ID)) //its a
notification