Exercise 3: Real-Time Data Communication (almost!)
Expected duration: 20 minutes — 5 minute introduction then 15 minutes for lab
The goal of this exercise is to learn how to use a timer and asynchronous event handler to gather data and communicate it to non-real-time parts of the system using a data communication channel that is supplied. In addition you will find (once again) that meeting your real-time requirements takes additional considerations in the code you use. The requirements are:
- Create a
PeriodicTimer set to fire every 50ms.
- Associate with that timer a non-heap-using instance of
AsyncEventHandler that, on each release, reads data from a "sensor" and pushes that data into an instance of the supplied DataBuffer data communication channel.
Warning: Threads with real-time priorities run to the exclusion of all non-realtime processes on the system, including operating system services, shells and GUIs! If your real-time thread does not explicitly block it will consume 100% of a CPU. If you have less CPUs than real-time threads doing this then you system may appear to lock-up. So take care with experimentation: an infinite loop may require a reboot to fix!
Background Information
Read the material in the presentation, up to the slide titled "Exercise 3".
- You've already seen how to create a periodic real-time thread in Exercise 1. Using a PeriodicTimer with an associated AsyncEventHandler is another way of expressing a periodic activity. The choice between them is often a matter of style, but if you need to pause your periodic activity, or to change the timing of it, then a timer has these capabilities built-in, while you would have to code them from scratch for a real-time thread.
- A no-heap AsyncEventHandler is created by passing a constructor argument (in contrast to threads where NoHeapRealtimeThread is a subclass of RealtimeThread). Ensure you set its priority to be greater than the RTGC!
- Give the handler periodic release parameters to reflect its periodic nature.
- On each release (that is on each firing of the timer) the AsyncEventHandler will be associated with a real-time thread supplied by the system, and that thread will execute the handler's handleAsyncEvent method. This method contains the code that you want to be executed every 50ms. In contrast to the periodic real-time thread, you do not have to write a loop that calls a special method to block until the next release — the asynchronous event handling mechanism takes care of that for you.
- We're concerned about not missing deadlines — which means that the handler must complete execution of its handleAsyncEvent method before the next release. While the handler could have its own deadline-miss handler installed, a simpler technique is to check the handler's pending release count: if this count is greater than zero then a deadline has been missed because another release is pending. Place the following code at the start of your handleAsyncEvent method to report deadline misses:
int pending = getAndClearPendingFireCount();
if (pending > 0) {
throw new Error("Deadline missed! - pending count " + pending);
}
- Your event handler is emulating a periodic activity that reads data from a device (an instance of Sensor in this example) and pushes that data to a communication channel (an instance of DataBuffer). In this exercise the data is unimportant and a simple double value will be used. Data is read from a Sensor using the read() method, and is pushed to the DataBuffer using the add(double d) method. The internal details of DataBuffer are not a concern in this exercise — but will be in the next!
- The data is extracted from the channel using a non-realtime consumer thread (an instance of ConsumerThread), and the data is "processed" prior to extraction. This consumer thread is setup for you by the Main program.
- Terminate the application by having your handler invoke System.exit(0); when it runs for the 100th time.
- To avoid unpredictable delays due to class-loading we're utilizing the Initialization Time Compilation (ITC) feature of Sun Java RTS. This is handled by the settings defined under Project Properties -> Real-Time Configuration. The use of ITC should be transparent to you for the purposes of these exercises, but you may see messages in the console output referring to the files itc.precompile and/or itc.preinit — these files have been provided for you in each of the project directories.
Steps to Follow
- Start the Netbeans IDE if not already started.
There are projects defined for each exercise and its solution.
Expand the project Ex3 by clicking on the "lollypop" icon to the far left
of the project name, in the project pane. Click on the same icon next to the Source Packages item to show
the packages defined in this project. Click on the same icon next to the ex3 package name to show all the source
files defined in this project. To edit a source file, double-click on its name and an editing tab for that file
will appear in the right-hand pane.
- Edit the
PeriodicAEH class (in PeriodicAEH.java ) and fill in the logic of the handleAsyncEvent() method, as indicated, to:
- Check for and report deadline misses
- Read a data value from the sensor and add it to the data buffer. Print each value to the console so that you can see that the handler is executing.
- Terminate the application on the 100th release of the handler.
- Edit the
Main class (in Main.java ) and add code, as indicated, to the main method to:
- Enable creation of an instance of the
PeriodicAEH class with a period of 50ms. You must create suitable PriorityParameters and PeriodicParameters objects
to pass to the PeriodicAEH constructor — similarly to what you did for Exercise 1.
- Create a PeriodicTimer, with an interval of 50ms, an immediate start time, and associated with your PeriodicAEH handler.
The main method contains code to start your timer. It also contains the code to construct and start an instance of ConsumerThread, but initially the starting of the consumer thread is commented out to allow testing of the handler in isolation.
- Build the project by right-clicking on the project name in the project pane, and then clicking on Build.
Correct any compilation errors and build again, repeating as necessary.
- Run the project:
- From within Netbeans by right-clicking on the project name in the project pane, and then clicking on Run.
The output will be displayed in the output pane at the bottom of the window.
- From a terminal window by executing
the command:
<INSTALL_DIR>/bin/java -jar /export/home/lab5538/realtimejava/exercises/Ex3/dist/Ex3.jar
Here's an example of part of what you might see:
# > /opt/SUNWrtjv/bin/java -jar /export/home/lab5538/realtimejava/exercises/Ex3/dist/Ex3.jar
Application started ...
Handler read 0.838178
Handler read 0.509115
Handler read 0.769864
Handler read 0.770645
Handler read 0.532167
Handler read 0.214572
Handler read 0.654716
Handler read 0.543998
Handler read 0.009298
Handler read 0.994716
Handler read 0.318251
Handler read 0.800169
Handler read 0.059500
Handler read 0.948770
Handler read 0.463608
Handler read 0.861470
Handler read 0.457297
Handler read 0.638196
Handler read 0.600030
Handler read 0.540824
Handler read 0.860600
Handler read 0.293279
Handler read 0.017523
Handler read 0.559786
Handler read 0.271924
Handler read 0.911921
Handler read 0.518982
Handler read 0.593962
Handler read 0.521680
Handler read 0.151931
Handler read 0.809336
Handler read 0.290957
Handler read 0.527086
Handler read 0.282341
Handler read 0.188365
Handler read 0.548342
Handler read 0.530486
Handler read 0.229791
Handler read 0.597124
Handler read 0.187805
Handler read 0.127269
Handler read
0.932772
Handler read 0.127523
Handler read 0.916478
Handler read 0.656316
Handler read 0.799551
Handler read 0.820399
Handler read 0.127618
Handler read 0.444799
Handler read 0.054828
Handler read 0.949502
Handler read 0.660166
Handler read 0.474404
Handler read 0.155710
Handler read 0.017135
Handler read 0.110364
Handler read 0.267460
Handler read 0.259314
Handler read 0.371746
Handler read 0.668466
Handler read 0.179161
Handler read 0.932361
Handler read 0.698623
Handler read 0.739755
Handler read 0.826014
Handler read 0.907335
Handler read 0.631866
Handler read 0.801409
Handler read 0.080846
Handler read 0.710327
Handler read 0.389177
Handler read 0.045432
Handler read 0.921140
Handler read 0.412415
Handler read 0.640542
Handler read 0.362732
Handler read 0.430169
Handler read 0.589458
Handler read 0.787728
Handler read 0.134558
Handler read 0.419339
Handler read 0.814416
Handler read 0.453570
Handler read 0.114903
Handler read 0.465366
Handler read 0.651855
Handler read 0.258343
Handler read 0.411100
Handler read 0.637317
Handler read 0.176009
Handler read 0.895102
Handler read 0.199727
Handler read 0.826287
Handler read 0.491805
Handler read 0.106680
Handler read 0.351078
Handler read 0.384397
Handler read 0.602516
Handler read 0.414092
Handler read 0.577811
Java Real-Time System HotSpot(TM) Client VM dumping compilation list in itc.precompile
Java Real-Time System HotSpot(TM) Client VM dumping preinit list in itc.preinit
Note: the application will attempt to terminate after 60 seconds, in case your event handler does not terminate when it should.
- When you're satisfied with the operation of your handler, uncomment the line in the main method that starts the consumer thread. Re-build and re-run your application.
Did your application complete successfully? Or did you see an exception like the following?
java.lang.Error: Deadline missed! - pending count 14
at ex3.PeriodicAEH.handleAsyncEvent(PeriodicAEH.java:43)
at javax.realtime.AsyncEventHandler.run1(AsyncEventHandler.java:855)
If you did, you won't be alone — there's something interfering with the timely execution of our periodic event handler — and this time we know it isn't the GC! — and in the next exercise you'll find out what it is this time.
Solution
The solution of this exercise is provided as a "ready to build and run" NetBeans project: <lab_root>/realtimejava/solutions/exercise3/Ex3Soln.
Summary
In this exercise, you learned how to create a periodic timer to release an event handler, and how to create an event handler to respond to events — both fundamental building block in many real-time systems. You also learned how to create a simple producer/consumer architecture to communicate data between the real-time and non-real-time parts of the system — but as with Exercise 1 you've seen that meeting deadlines isn't always straight-forward.
Back to top
Next exercise
|