ABSTRACT
This thesis focuses on the modeling concept....
NEATTOOLS-A FINE GRAIN DATA FLOW NETWORK PROGRAMMING ENVIRONMENT
By
YUH-JYE CHANG
DISSERTATION
Submitted in partial fulfillment of the requirements for the degree of Doctor of Philosophy in Computer Information Science in the Graduate School of Syracuse University
Dec 1998
Approved _________________________
Professor Geoffrey Fox
Date _____________________________
Copyright 1998 Yuh-Jye Chang
All rights Reserved
CONTENTS
1. Introduction
2. Project Requirements
3. C++ vs. Java
3.1 Java Background
3.2 Benchmark
3.3 Benchmark Analyze
3.4 Conclusion
4. NeatTools Architecture Analyze
4.1 Module Abstraction
4.1.1 Data
4.1.1.1 The presentation
4.1.1.2 Access privilege
4.1.1.3 The desktop
4.1.2 Actions
4.1.2.1 Active (Output) action
4.1.2.2 Reactive (Input) action
4.1.3 Connections
4.2 Implementation Concept
4.3 Benchmark Information on NeatTools
4.4 Benchmark Analyze on NeatTools
4.5 Conclusion
5. NeatTools and Object Management Environments
5.1 CORBA
5.1.1 Object Definition
5.1.2 CORBA provide Object Interoperability
5.1.3 OMA provide Application-Level Integration
5.2 COM/DCOM
5.2.1 Objects and Interfaces
5.2.2 Interface Description Language (IDL)
5.2.3 Service Control Manager (SCM)
5.3 Compare COBRA and COM/DCOM
5.4 Benchmark Information on CORBA
5.5 Benchmark Analyze on CORBA
5.6 Conclusion
6. NeatTools and Modeling Languages
6.1 Colored Petri-Net
6.2 UML (Unified Modeling Language)
6.3 Conclusion
7. NeatTools and Other Visual Programming Tools
7.1 Visual C++
7.2 Visual Basic
7.3 Java Bean
7.4 J++
7.5 LabView
7.6 AVS
7.7 Conclusion
8. NeatTools' Visual Programming Features
8.1 Multimedia Database
8.2 Transfer Focus among Text Fields
8.3 Polymorph Data Type
8.4 Container Nest Structure (Complex Module)
8.5 Data Flow Controls
8.6 Multimedia Features
8.7 Multi-Thread Features
8.8 Keyboard and Mouse Event Simulator/Filter
8.9 External Module and Dynamic Link Library
8.10 Modules for External Devices
8.11 Networking and TCP/IP
8.12 State Machine
9. Examples/Applications
10. Conclusion
11. Appendix
11.1 NeatTools Reference Manual
11.1.1 NeatTools Module Specification:
11.1.2 NeatTools Class Hierarchy:
11.2 Module Programming Examples
11.3 Visual Programming Examples
11.4 NeatTools Architecture
11.4.1 Three-Layer Architecture
11.4.2 Package structure
11.4.3 OS and C++ runtime Package
11.4.4 Java-like API package
11.4.4.1 LANG package
11.4.4.2 UTIL package
11.4.4.3 IO package
11.4.4.4 NET package
11.4.4.5 AWT package
11.4.5 NeatTools application package
11.4.5.1 NEAT package
11.4.5.2 Modules package
11.4.5.3 External modules package
11.4.5.4 DESKTOP package
12. Bibliography
FIGURES
Figure 1: Top-level packages
Figure 2: OS and C++ runtime layer
Figure 3: Java like cross-platform API layer
Figure 4: Exceptions class diagram in Java like API layer
Figure 5: NeatTools application layer
Figure 5: Property in NEAT package
Figure 7: NEAT package (continue)
TABLES
Table 1: Summary of layers
Table 2: Classes of LANG package
Table 3: Classes of UTIL package
Table 4: Classes of IO package
Table 5: Classes of NET package
Table 6: Classes of AWT package
Table 7: Classes of NEAT package
NeatTools is a visual programming software package with which a user can create module linkage networks for data collection, gesture recognition, control of external devices, virtual world control, remote collaboration, and perceptual modulation. Some of NeatTools' functionality is ported from Neat Software developed for Dr. Dave Warner at the Institute for Interventional Informatics from 1993 to 1996.
NeatTools' visual interface is similar to AVS. Different modules are selected, placed in a work area, and then connected by lines. These connections indicate a data flow from one module to another. The data flow may be comprised of various data types (e.g., integer, real number, string, MIDI event, wave stream, video stream, etc.). NeatTools provides multi-threaded, real time support in module design which is not supported by AVS. These features bring a NeatTools user full power to access the resources inside the computer.
The software is written in C++ and built on top of a Java-like Cross Platform C++ API (application programming interface). We decided against using Java because we need the software to be capable of handling real time computationally intensive tasks like audio, video, compression, decompression, VR, etc. We designed the graphical user interface (GUI) API after the Java API standard as all features implemented in a Java API are intrinsic to standard windows systems like Microsoft Windows and X Windows. By hiding all platform-dependent code inside the API, we achieve our goal of a cross platform application by maintaining only one code package. Currently, NeatTools can compile and run on Win95, WinNT, LINUX, Sun, and SGI. On Win95, or WinNT we use Microsoft Visual C++ 5.0. On UNIX we use GNU GCC 2.7.2.
The NeatTools environment is extensible. New modules can be added by invoking dynamic linkage libraries which specify an implementation of the module. Later, a user can use it just like any predefined module and create new module linkage networks.
NeatTools is an experimental computer science project. Before we can make any experiment, we have to have a tool or environment. On top of it, we than can build and test our design concept and proceed the experiment itself. So, the first step was to implement such a visual programming tool. The question was which language to use to implement the tool so it will meet all the requirements and has the potential for the future development. Here, C/C++ is the industry standard and Java is a rapid develop and well adopted new language. I dedicated the following sections to discuss the cons and pros of this two popular language.
Java is an object-oriented programming language developed by Sun Microsystems, a company best known for its high-end Unix workstations. Modeled after C++, the Java language was designed to small, simple, and portable across platforms and operating systems, both at the source and at the binary level.
Platform independence is one of the significant advantages that Java has over other programming languages. At the source level, Java's primitive data types have consistent sizes across all development platforms. Java's foundation class libraries make it easy to write code that can be moved from platform to platform without the need to rewrite it to work with that platform. Java binary files are also platform-independent and can run on multiple platforms without the need to recompile the source. How this work? Java binary files are actually in a form called bytecodes. Unlike most other programming language, Java development environment has two parts: a Java compiler and a Java interpreter. The Java compiler takes Java program and instead of generating machine code from source files, it generates bytecodes. To run a Java program, user run a program called a bytecode interpreter, which in turn executes Java program. User can either run the interpreter by itself, or for applets there is a bytecode interpreter built into Java-capable or enabled browser like Netscape or Microsoft Internet Explorer that runs the applet.
The disadvantage of using bytecodes is in execution speed. Because system-specific programs run directly on the hardware for which they are compiled, they run significantly faster than Java bytecodes which must be processed by the Java interpreter. In order to increase the performance of Java bytes, some companies are dedicate on accelerating the bytecode. JIT (just in time) interpreter is one of the technology that are widely adapted into the commercial Web browser. JIT interpreter usually load the Java bytecodes preprocess it into system-specific code in a dynamically fashion and then execute the system-specific code directly.
I wrote a simple Java benchmark program:
import java.applet.Applet;
public class benchmark extends Applet {
public int dummy(int i) { return i;}
public void start() {
int i, x;
x = 0;
System.out.println("Benchmark Start");
long b1 = System.currentTimeMillis(), b2;
for (i=0; i<100000000; i++) {
}
b2 = System.currentTimeMillis();
System.out.println("Empty For Loop "+(b2-b1));
b1 = b2;
for (i=0; i<100000000; i++) {
x += i;
}
b2 = System.currentTimeMillis();
System.out.println("For Loop with + and assign "+(b2-b1));
b1 = b2;
for (i=0; i<100000000; i++) {
x *= i;
}
b2 = System.currentTimeMillis();
System.out.println("For Loop with * and assign "+(b2-b1));
b1 = b2;
for (i=0; i<100000000; i++) {
x += dummy(i);
}
b2 = System.currentTimeMillis();
System.out.println("For Loop with function call and assign "+(b2-b1));
}
}
Translate the Java program into C++ would be:
#include <stdio.h>
#include <sys/timeb.h>
long currentTimeMillis() {
struct _timeb tstruct;
_ftime(&tstruct);
return tstruct.time*1000+tstruct.millitm;
}
class benchmark {
public:
int dummy(int i) { return i;}
void start() {
int i, x;
x = 0;
printf("Benchmark Start\n");
long b1 = currentTimeMillis(), b2;
for (i=0; i<100000000; i++) {
}
b2 = currentTimeMillis();
printf("Empty For Loop %d\n", b2-b1);
b1 = b2 = currentTimeMillis();
for (i=0; i<100000000; i++) {
x += i;
}
b2 = currentTimeMillis();
printf("For Loop with + and assign %d\n", b2-b1);
b1 = b2 = currentTimeMillis();
for (i=0; i<100000000; i++) {
x *= i;
}
b2 = currentTimeMillis();
printf("For Loop with * and assign %d\n", b2-b1);
b1 = b2 = currentTimeMillis();
for (i=0; i<100000000; i++) {
x += dummy(i);
}
b2 = currentTimeMillis();
printf("For Loop with function call and assign %d\n",
b2-b1);
}
};
void main() {
benchmark bm;
bm.start();
}
The test data are following (Test on PC with AMD-233MHZ CPU, Win95) :
Units (ms) |
for loop 108 |
x += i |
x *= i |
x += dummy(i) |
C++, VC++ |
0 * |
880 |
1810 |
880 |
JDK 1.1 |
29000 |
50420 |
51300 |
110730 |
JDK 1.0 |
43830 |
82340 |
83210 |
170210 |
IE 4.0 |
42400 |
63330 |
63820 |
175550 |
IE 4.0 (JIT) |
0* |
930 |
2250 |
9010 |
Netscape 4.05 |
940 |
1810 |
2690 |
8510 |
* Optimized and eliminated by compiler or interpreter.
Units (us/loop) |
for loop |
x += i |
x *= i |
x += dummy(i) |
C++, VC++ |
0 * |
0.0088 |
0.0181 |
0.0088 |
JDK 1.1 |
0.29 |
0.5042 |
0.513 |
1.1073 |
JDK 1.0 |
0.4383 |
0.8234 |
0.8321 |
1.7021 |
IE 4.0 |
0.424 |
0.6333 |
0.6382 |
1.7555 |
IE 4.0 (JIT) |
0* |
0.0093 |
0.0225 |
0.0901 |
Netscape 4.05 |
0.0094 |
0.0181 |
0.0269 |
0.0851 |
* Optimized and eliminated by compiler or interpreter.
Base on the nature of the object oriented programming, the function call is a must. The class interface are actually functions associated with objects. From the table above we learn that the most advanced commercial browser's Java interpreter are above 10 times slower than compiled C++ code when a function call is involved in the loop. And when the Java interpreter doesn't equip with JIT, the ratio become unacceptable slow (around 200 times slower). And this is only a very simple benchmark program. When it comes to large application, the JIT will tends to have worse performance because it has limited buffer for compiled code. If the whole application is too large to be compiled before it execute, the JIT interpreter will have to compile section by section on the fly and slow down the execution speed. I estimate the JIT will run about 20 times slower than compiled C++ code when application is relatively large.
Eighteen months ago, when I start to design the forth generation of NeatTools project, I insist to use C++ instead of Java. The top reason for that is speed. At that time, the JIT technology is not mature yet. Even today the JIT Java interpreter is still not fast enough for mission critical and calculate intensive real-time task like compress/decompress of voice and video data. The only chance that Java's speed will comparable with C++ is Java chip which could execute Java bytecode directly. But it will be a while before the product become popular and inexpensive. There are some other solutions such as link native code into Java program or using tools to convert Java bytecode into native code, etc. But again, these alternatives lost the portability that Java bytecode provide. To avoid all those trouble and overhead, I use C++ and build the Cross Platform API (please reference the Appendix NeatTools Architecture section) which let C++, an already robust and industry standard language, become easy to port on different platform and also equip it with a multi-threaded GUI capable programming interface. I think I made the right decision for this project.
In NeatTools, the most important concept are the module abstraction. The module abstraction simplify and model all the interactions between module into active actions and reactive actions. Later in this section, I discuss the implementation concept and present some benchmark information and analyze it.
In NeatTools, module abstraction is offered as a set of class methods that provides inter-module communication functionality. Functional components (implemented as class objects) of a concurrent system are written as encapsulated modules that act upon local data structures, or objects inside object classes, some of which may be broadcast for external use. Relationships among modules are specified by logical connections among their broadcast data structures. Whenever a module updates data and wishes to broadcast the change, and make it visible to other connected modules, it should implicitly call an output service function which will broadcast the target data structure according to the configuration of logical connections. Upon receiving the message event, the connected modules execute its action engine according to the remote data structure. Thus, output is essentially a byproduct of computation, and input is handled passively, treated as an instigator of computation.
This approach simplifies module programming by cleanly separating computation from communication. Software modules written using module abstraction do not establish or effect communication, but instead are concerned only with the details of the local computation. Communication is declared separately as logical relationships among the state components of different modules.
This programming model has its roots in the formal Input / Output automaton model of Lynch and Tuttle [1]. An I/O automaton is a state machine with a signature consisting of a set of input actions and a set of locally controlled actions. The locally controlled actions could divide into output actions and internal actions. Locally controlled actions are under the control of the automaton, while input actions may occur at any time. Automata may be composed such that when an output action of one automaton occurs, all automata having a same-named action as an input action make a state transition simultaneously. A behavior of an I/O automaton is a sequence of input and output actions that may occur in an execution of that automaton. The module abstraction programming model is designed to benefit from the useful characteristics of the I/O automaton model that are helpful in reasoning formally about distributed systems.
Module abstraction is based on three fundamental concepts: data, actions, and connections. It is difficult to discuss these concepts in detail without reference to particular mechanisms for supporting them. Therefore, we present them in the context of NeatTools, a software package, run-time system and visual programming environment we have designed to support the development of data flow network applications using module abstraction.
Data (the components of a module's state, could be data structures or objects) may be kept private or they may be broadcast when needed so that other modules may access the data. NeatTools provides a base abstract class object that declares the basic data structure and service procedures (or methods). Every module object should inherit from this class object and override some of the predefined procedures to serve the different computational and presentational needs of each module. NeatTools provides a library of data types for declaring data that may be broadcast. These include integer, real, string, block, byte array, midi event, voice stream, and video stream. The module programmer may define others.
Each NeatTools module has a presentation that presents itself to the user as the visual feedback. It could be graphics images, shapes, or text. The presentation may change dynamically according the current state. Associated with each data item are a public name, property, access privileges, and data type. This information helps a user understand its presentation. The data type and access privileges also permit type check and privilege match of logical connections.
Access privileges include input, output, insert, and connect. Output access allows connected modules to observe the value of the data when broadcast event message. Input access allows a module to change the state of the target module. Insert access allows a new connection to be inserted into an aggregate item of a module. Connect access allows a module to relate the data item to a data item of some other module. All those access privileges are controlled by a set of class methods (already defined in the base abstract class). By overriding those methods, modules could change the behavior or dynamically control access behavior according the current state of module.
A NeatTools module interacts with a desktop and a collection of other modules that may be unknown to this module but that read and modify the data item in its presentation when permitted by the access privileges. The desktop also works as a graphical user interface front end that provides a user with a set of layout service functions, including move, resize, copy, delete, group, ungroup, connection management, object persistency management and file input/output.
The action portion of a module defines how its state changes over time and responds to an environment. Insulated from the structure of its environment, a NeatTools module interacts entirely through the broadcast service procedure and reactive execution engine procedure. A module may autonomously modify its local state, and it may react to the incoming events and change its local state. This suggests a natural division of the actions into two parts: active action and reactive action.
The active action carries out the ongoing computation of the module. For example, in a discrete event simulation, the active action would be iterative computation that simulates each event. External updates of simulation parameters could affect the course of future iterations, but would not require any special activity at the time of each change. Modules with only active action can be quite elegant since input simply steers the active computation without requiring a direct response. Active action is analogous to the locally controlled actions of an I/O automaton.
The reactive action carries out activities in response to input from the environment. A module with primarily reactive action simply reacts to input from the environment, updating its local state and presentation as dictated by the input change. For example, a data visualization module could be constructed so that each time some data element changes, the visualization is updated to reflect the change. In the above discrete event simulation, one might add reactive action to check the consistency of simulation parameters that are modified by the environment. Reactive action is analogous to the input actions of an I/O automaton.
Relationships between data items of different modules are declared with logical connections between those data items. These connections define the communication pattern of the system. Connections are established by a special NeatTools module, called a desktop, that enforces type compatibility across connections and guards against access protection violations by establishing only authorized connections.
Connections are declared separately from modules so that one can design each module with a local orientation and later connect them together in various ways. Connections are designed to accommodate all kinds of data types varying from integer, real to audio and video. The run-time system could handle the communication requirements automatically according to the module abstraction of the module.
If we liken the data items of a NeatTools module to the actions in the signature of an I/O automaton, then just as like-named actions in automaton signatures define the sharing of actions, connections define the sharing of state change information. Currently, a simple synchronous data transmission algorithm is used by the broadcast service procedure. The reactive action engine of a connected module will be invoked and executed automatically. However, if asynchronous data transmission is needed, user could construct a data queue inside the module and react to the data queue later. This way, we can keep the general communication structure simple and efficient.
NeatTools' design concept is base on a different aspect of application design which provide visual programming capacity. In traditional textual programming design, lines of code are the rough measure of program size. In visual programming design like NeatTools data flow network, number of connections and modules become the major indications. So how NeatTools provide an efficient way to broadcast and process message events between modules become the most important issue. In NeatTools every modules are already class objects. The only object interoperability are simplified into active and reactive actions, or connections. In order to increase the application throughput, the connections in NeatTools are just logical reference. The message broadcast are actually perform by direct function call to ensure the performance of NeatTools' data flow network. For those remote message passing between NeatTools and remote computer running NeatTools, they performed by Socket and ServerSocket modules (just like regular modules, but they perform different task) to handle all the data communication task (usually on top of TCP/IP which is slow compare to direct function call). Connections between Socket and other modules are still the same efficient function call. So, instead of network connection oriented design (like CORBA), NeatTools use direct function call oriented design and eliminate all possible overhead and layers.
I wrote a special benchmark module in NeatTools. Which has two inputs and one output. The one on top can enabled and start the benchmark. The one on left can receive message event from other benchmark module but do nothing. When the module is enabled, it will start the benchmark by broadcast events through its output port in a 106 loop and then display the time interval in the debug dialog box. The benchmark here is focus on the overhead of message broadcasting in NeatTools.
The engine method of the benchmark module was implemented as following:
void JBenchmarkObj::engine(int n, JLinkObj& link) {
if (!n) {
// link.access(JIntegerData(v[0]));
} else {
int oldv = v[1];
link.access(JIntegerData(v[1]));
v[1] = (v[1] != 0);
if ((v[1] != oldv) && !v[1]) {
int time = JSystem::currentTimeMillis();
for (int i=0; i<1000000; i++)
broadcast(0);
time = JSystem::currentTimeMillis()-time;
JComponent::debug(JInteger::toJString(time)+" ms");
}
}
}
The NeatTools benchmark data flow network are arranged as following:
The five test modules are instances of benchmark module. One of them connects its enabled input from button and its output connects to the rest of the test modules.
The benchmark data for this particular data flow network running on my PC (AMD-233MHZ CPU, Win95) is 2200 ms. Because the output has four connections and the broadcast process are repeated for 106 times. So 2200 ms / 4 / 106 become 0.55 us per connection broadcast which is just 6.25 times slower compare to the direct function call with only one statement. In other word, NeatTools is capable of dispatch around 1,800,000 messages in one second. At this speed, I believe NeatTools could handle most real-time or calculate intensive task on the data flow network level.
The contribution of this section is focus on how I proposed an abstract module model. Base on this model, I proposed a simplified and high performance way to implement the module connections and how we map the connections into directly function call without much overhead and layers. This model proved to be successfully implement in the NeatTools project. Currently, we have a lot of NeatTools data flow networks on data collection, gesture recognition, control of external devices, virtual world control, remote collaboration, and perceptual modulation. With the scalable design of NeatTools project, I believe NeatTools could be widely adapted to almost any real world problems and provide complete and fast solutions.
Object Managements Group (OMG)'s Object Management Architecture (OMA): the multi-vendor standard for object-oriented distributed computing. This includes CORBA -- the Common Object Request Broker Architecture -- which most people associated with OMG; the CORBAservices and CORBAfacilities.
Objects are discrete software components -- they contain data, and can manipulate it. Usually, they model real-world objects, although sometimes it's useful to create objects specifically for things we want to compute. Other software components send messages to objects with requests; the objects send other messages back with their responses.
In order for objects to plug and play together in a useful way, clients have to know exactly what they can expect from every object they might call upon for a service. In CORBA, the services that an object provides are expressed in a contract that serves as the interface between it and the rest of our system. The interfaces are expressed in OMG Interface Definition Language -- OMG IDL -- making them accessible to objects written in virtually any programming language, and the cross-platform communications architecture is the Common Object Request Broker Architecture -- CORBA.
Base on CORBA architecture, the OMA specifies a set of standard interfaces and functions for each component. Different vendors' implementations of the interfaces and their functionality then plug-and-play on customers' networks, allowing integration of additional functionality from purchased modules or in-house development.
The OMA is divided into two major components: lower-level CORBAservices and intermediate-level CORBAfacilities. The CORBAservices provide basic functionality that almost any object might need: object lifecycle services such as move and copy, naming and directory services, and other basics. The CORBAfacilities architecture has two major components: one, horizontal, including facilities such as compound document services which can be used by virtually every business; and the other, vertical, standardizing management of information specialized to particular industry groups.
COM (Component Object Model) is a software architecture that enables program to be built from smaller binary components. It is a binary standard for component interoperability and is independent of programming language.
COM supports a client/server model between the user of some object's services and the implementers of that object and its services. COM's role is to establish the connection between the client and the server, which offers the desired object. Once the connection has been made, COM is out of the picture and all communication goes directly from server to client and vice versa.
In COM an object is an instance of a class which as in standard OO terminology is a set of data and related functionality. Unlike most other OO models, COM provides no direct access to object data. Instead user have to access member functions of an associated interface.
An interface is a set of functions that can be invoked on a given object. Interfaces do not contain any implementation what so ever, but merely defines the expected behavior of an object. When an object implements an interface, it provides implementations for every function in the interface, and provides pointers to those functions to COM.
COM's Interface Description Language (IDL) is base on the Open Software Foundation (OSF) Distributed Computing Environment (DCE) specification for describing interfaces, operations, and attributes to define remote procedure calls.
A designer can define a new custom interface by writing an interface definition file. The interface definition file use the IDL to describe data types and member functions of an interface. The interface definition file contains the information that defines the actual contract between the client application and server object.
The SCM is a COM component that is able to locate a given server and launch it. The SCM contains a database of class information. When a client requests the COM library to create an object, the SCM is launched, the server located and run. Here SCM provide the object interoperability.
From the communication point of view, COM is a little bit different from CORBA. In CORBA, ORB is always the gateway between its object client and server. The client and server in CORBA never communicate each other directly. In COM, SCM locate and lunch the object server for application client and then the client communicate directly with the server. Also COM has different mechanisms for in-process, cross-process, and remote object server. In in-process case, the SCM will locate and load the object server as a DLL. So in this situation, the object server will be executed in the client's process space which is much faster than COBRA's mechanism. In cross-process case, the SCM will locate and load the object server as an executable. The object server will be executed in a separate process space. So it is slower than the DLL but still faster then the COBRA's mechanism. Even in remote object server case, the SCM will contact the remote SCM and later on build a remote proxy server which can forward requests directly to the remote SCM via the RPC connection. So, in general, COM/DCOM have better performance over COBRA. But COBRA have better sense base on system and structure concern. For example, a COBRA's object server will only deal with its local ORB. But a DCOM's object will have to deal with local SCM, in-process client, cross-process client, and remote client.
From the application point of view, COM is lack of application integration packages. COBRA's CORBAservices and CORBAfacilities components provide the application-level integration which provide lower-level and intermediate-level services for industry and business applications.
The most important advantage that Object Management Environments like CORBA, and COM/DCOM is the object interoperability. The object interoperability make objects to plug and play together in a useful way become possible. But the advantage comes with the price -- speed. For example, in CORBA, when an object client issue a function call to a remote server object, it has to go through the IDL Stub (created by IDL), Object Request Broker (ORB), remote ORB, IDL Skeleton, and finally reach the remote server object implementation. And in most case it go through the network communication layer like TCP/IP at least twice (forward the request and send back the result message) to complete a function call.
I visited one of the ORB vender site which has a web page dedicate to the performance information. URL for this page is http://www.orl.co.uk/omniORB/omniORBPerformance.html. On this page, one of the table are following:
Performance of omniORB2 on various platforms.
Platform |
Transport |
Protocol |
us/call |
Linux Pentium Pro 200 MHz |
IP/intra-machine |
IIOP |
340 |
IP/ethernet (ISA) |
IIOP |
1000 |
|
IP/ATM |
IIOP |
440 |
|
AAL5/ATM |
IIOP |
350 |
|
Windows NT Pentium Pro 200 MHz |
IP/intra-machine |
IIOP |
360 |
IP/ethernet (ISA) |
IIOP |
1000 |
|
Digital Unix 3.2 Alpha DEC 3000 |
IP/intra-machine |
IIOP |
750 |
IP/ethernet |
IIOP |
1050 |
|
Windows '95 Pentium 166 MHz |
IP/intr-machine |
IIOP |
1000 |
IP/ethernet (PCI) |
IIOP |
1250 |
|
Solaris 2.51 Ultra 1 167 MHz |
IP/intra-machine |
IIOP |
540 |
IP/ethernet |
IIOP |
710 |
From the table above, to make a function call, even the function call is made within the machine (the IP/intr-machine), it make about 360 us on a Pentium Pro 200MHz machine. If we compare the benchmark information with the previous section, make a direct function call in compiled C++ code only take 0.0088 us which is about 41,000 times faster than make a function calls on this particular ORB. For those call that are made remotely by direct network card connection (the IP/ethernet), it take 1,000 us to make a function calls. In that case it is about 114,000 times slower than the compiled C++ code.
CORBA and COM/DCOM provide the object interoperability which is a great feature for object plug and play and object reusability. But this functionality comes with a big draw back -- decrease the performance in a huge fashion especially in CORBA. In COM/DCOM, the performance problem is lesser. It is possible that NeatTools project build upon CORBA or COM/DCOM architecture. NeatTools module designer will be able to put the modules on line and let user access it remotely. But, NeatTools will have to limit data flow design with modules which does not require a lot of message event passing. For those fine grain modules such as digital logic, number, and real number operation module, decrease the message passing speed will hurt the performance a lot. In this case, we won't be able to build data flow network in NeatTools complex enough to meet the requirements as a general human interface tool.
Colored Petri-Net (CP-nets or CPN) is a graphical oriented language for design, specification, simulation and verification of systems. It is in particular well-suited for systems witch communication, synchronization and resource sharing are important. Typical examples of application areas are communication protocols, distributed systems, imbedded systems, automated production systems, work flow analysis and VLSI chips.
The Unified Modeling Language (UML) is a language for specifying, visualizing, constructing, and documenting the artifacts of software systems, as well as for business modeling and other non-software systems. The UML represents a collection of best engineering practices that have proven successful in the modeling of large and complex systems.
One of most important issue in fast prototyping with existing program is that if we can build a Keyboard or Mouse event simulator. By transfer the action into simulated keyboard or mouse events, the existing program will think that the keystroke or mouse movement is coming from user interaction.
Name: NOTObj
Input: "input" integer port on the left edge with unlimited connections.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate the bit wise NOT operation on the input values and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical (1-bit) NOT operation. When it is 16, it will become the 16 bit wise NOT operation.
Name: ANDObj
Input: "input" integer port on the left edge with unlimited connections.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate the bit wise AND operation on the input values and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical (1-bit) AND operation. When it is 16, it will become the 16 bit wise AND operation.
Name: ORObj
Input: "input" integer port on the left edge with unlimited connections.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate the bit wise OR operation on the input values and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical (1-bit) OR operation. When it is 16, it will become the 16 bit wise OR operation.
Name: XORObj
Input: "input" integer port on the left edge with unlimited connections.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate the bit wise XOR operation on the input values and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical (1-bit) XOR operation. When it is 16, it will become the 16 bit wise XOR operation.
Name: GreaterThanObj
Input: "input-1" integer port on the left edge and "input-2" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Compare the value of "input-1" and "input-2" and broadcast the result value to "output" port when receiving an input event. Result value is true when "input-1" is larger "input-2", false otherwise.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical operation (true=1, false=0). When it is 16, it will become the 16 bit operation (true=0xFFFF, false=0x0000).
Name: GreaterEqualObj
Input: "input-1" integer port on the left edge and "input-2" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Compare the value of "input-1" and "input-2" and broadcast the result value to "output" port when receiving an input event. Result value is true when "input-1" is greater or equal "input-2", false otherwise.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical operation (true=1, false=0). When it is 16, it will become the 16 bit operation (true=0xFFFF, false=0x0000).
Name: EqualObj
Input: "input-1" integer port on the left edge and "input-2" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Compare the value of "input-1" and "input-2" and broadcast the result value to "output" port when receiving an input event. Result value is true when "input-1" is equal "input-2", false otherwise.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical operation (true=1, false=0). When it is 16, it will become the 16 bit operation (true=0xFFFF, false=0x0000).
Name: NotEqualObj
Input: "input-1" integer port on the left edge and "input-2" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Compare the value of "input-1" and "input-2" and broadcast the result value to "output" port when receiving an input event. Result value is true when "input-1" is not equal "input-2", false otherwise.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical operation (true=1, false=0). When it is 16, it will become the 16 bit operation (true=0xFFFF, false=0x0000).
Name: AddObj
Input: "input" integer port on the left edge with unlimited connections.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate the sum of all the input values and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: MultiplyObj
Input: "input" integer port on the left edge with unlimited connections.
Output: "output" integer port on the right edge with unlimited connections.
Function: Multiply all the input values and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: SubstractObj
Input: "input-1" integer port on the left edge and "input-2" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate "input-1" - "input-1" and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: DivideObj
Input: "input-1" integer port on the left edge and "input-2" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate "input-1" / "input-2" and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: AbsObj
Input: "input" integer port on the left with maximum one connections.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate ABS("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: PowObj
Input: "input-1" integer port on the left edge and "input-2" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate "input-1" ^ "input-2" and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: MaxObj
Input: "input" integer port on the left edge with unlimited connections.
Output: "output" integer port on the right edge with unlimited connections.
Function: Choose the maximum input value and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: MinObj
Input: "input" integer port on the left edge with unlimited connections.
Output: "output" integer port on the right edge with unlimited connections.
Function: Choose the minimum input value and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RemainObj
Input: "input-1" integer port on the left edge and "input-2" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate "input-1" % "input-2" and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RandomObj
Input: "control(logical)" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: When detect a raise edge signal event (from false to true) on the "control(logical)" port, this module will generate a random integer number and broadcast the result value to "output" port.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF).
Name: ControlObj
Input: "N(1-512)" and "control(logical)" integer port on the top edge and "in-0", "in-1", ..."in-(N-1)" polymorph ports on the left edge with maximum one connection.
Output: "out-0", "out-1", ..."out-(N-1)" polymorphs port on the right edge with unlimited connections.
Function: "N(1-512)" will determine the number of input-output pair. When detect a raise edge signal event (from false to true) on the "control(logical)" port, this module will connect the input-output pairs. So when there are input events presented on say "in-k", this module will transmit them into the corresponding "out-k" output port.
Properties: "moduleColor" set the background color. "N(1-512)" set the number of the input-output pair.
Name: SampleObj
Input: "N(1-512)" and "control(logical)" integer port on the top edge and "in-0", "in-1", ..."in-(N-1)" polymorph ports on the left edge with maximum one connection.
Output: "out-0", "out-1", ..."out-(N-1)" polymorphs port on the right edge with unlimited connections.
Function: "N(1-512)" will determine the number of input-output pair. When detect a raise edge signal event (from false to true) on the "control(logical)" port, this module will sample the current input value from input port say "in-k" and transmit into the corresponding "out-k" output port.
Properties: "moduleColor" set the background color. "N(1-512)" set the number of the input-output pair.
Name: PulseObj
Input: "input(logical)" integer port on the left edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: When receiving an input event, this module will generate an true-false event pair to the "output" port.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical operation (true=1, false=0). When it is 16, it will become the 16 bit operation (true=0xFFFF, false=0x0000).
Name: DelayObj
Input: "input(logical)" integer port on the left edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: When receiving an input event, this module will hold the value and broadcast the value when next input event comes in.
Properties: "moduleColor" set the background color.
Name: AccumulatorObj
Input: "enable(logical)" integer port on the top edge and "clock(logical)" integer port on the left edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: When receiving a raise signal (from false to true) event on "clock" port and current value of "enable" port is true, this module will increase the internal integer accumulator and broadcast the value to the "output" port. If receive a drop signal (from true to false) event on "enable" port, the internal integer accumulator will reset to zero and broadcast the value to the "output" port.
Properties: "moduleColor" set the background color.
Name: MultiplexerObj
Input: "N(2-512)" and "select" integer port on the top edge and "in-0", "in-1", ..."in-(N-1)" polymorph ports on the left edge with maximum one connection.
Output: "output" polymorphs port on the right edge with unlimited connections.
Function: "N(2-512)" will determine the number of input port. When receiving an input event on "select" port say k, this module will connect the selected "in-k" input port to "output" port. So when there are input events presented on "in-k" port, this module will transmit them into the "output" port.
Properties: "moduleColor" set the background color. "N(2-512)" set the number of the input port. "select (0-(N-1))" set the current selected input port.
Name: DeMultiplexerObj
Input: "N(2-512)" and "select" integer port on the top edge and "input" polymorph ports on the left edge with maximum one connection.
Output: "out-0", "out-1", ... "out-(N-1)" polymorphs port on the right edge with unlimited connections.
Function: "N(2-512)" will determine the number of output port. When receiving an input event on "select" port say k, this module will connect the selected "input" input port to "out-k" port. So when there are input events presented on "input" port, this module will transmit them into the "out-k" port.
Properties: "moduleColor" set the background color. "N(2-512)" set the number of the output port. "select (0-(N-1))" set the current selected output port.
Name: EncoderObj
Input: "N(2-32)" integer port on the top edge and "in-0", "in-1", ..."in-(N-1)" integer ports on the left edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: "N(2-32)" will determine the number of input port. When receiving an input event on input port, this module will encode all the output value, encode it into an integer and transmit them into the "output" port. For example, when N = 4 and the input value from "in-0", .."in-3" are 1, 0, 0, 1, this module will encode 1001 binary value into output integer value 9.
Properties: "moduleColor" set the background color. "N(2-32)" set the number of the input port.
Name: DecoderObj
Input: "N(2-32)" integer port on the top edge and "input" integer ports on the left edge with maximum one connection.
Output: "out-0", "out-1", ..."out-(N-1)" integer port on the right edge with unlimited connections.
Function: "N(2-32)" will determine the number of input port. When receiving an input event on input port, this module will decode the input value into the decoded bit value and transmit them into the corresponding output port. For example, when N = 4 and the input value is integer 9, this module will decode it into 1001 binary value and send out 1, 0, 0, and 1 into "out-0", "out-1", "out-2", and "out-3" output ports.
Properties: "moduleColor" set the background color. "N(2-32)" set the number of the output port.
Name: ClockDividerObj
Input: "N(2-512)" integer port on the top edge and "clock(logical)" integer ports on the left edge with maximum one connection.
Output: "out-0", "out-1", ..."out-(N-1)" integer port on the right edge and "value" integer port on the bottom edge with unlimited connections.
Function: "N(2-512)" will determine the number of output port. When receiving an raise signal (from false to true) on "clock(logical)" port, this module will increase an internal counter say k (k = 0..(N-1)) and transmit a true signal to the corresponding "out-k" output port. So when N=10, the output frequency will be 1/10 of the input frequency.
Properties: "moduleColor" set the background color. "N(2-32)" set the number of the output port. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF).
Name: TimeObj
Input: None.
Output: "output" date port on the right edge with unlimited connections.
Function: will send out date event every one second. Use the DateObj to show the current time and get the seconds, minutes, etc.
Properties: "moduleColor" set the background color.
Name: TimerObj
Input: "enabled(logical)" and "interval" integer port on the top edge with maximum one connection.
Output: "output" integer port on the right edge and "interval" integer port on the bottom edge with unlimited connections.
Function: When "enabled" is true (default is true), this module will send out integer pulse to "output" port event every "interval" millisecond. The "interval" input and output ports are for two way communication to external integer objects. So the value will keep consist when user modify the interval by property dialog box.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF). "delay" set the interval value in millisedond.
Name: CalibrateObj
Input: "calibrate(logical)", "lower" and "upper" integer port on the top edge and "input", "feedback" integer port on the left edge with maximum one connection.
Output: "output" and "decalibrate" integer port on the right edge and "lower", "upper" integer port on the bottom edge with unlimited connections.
Function: When "calibrate" is true, this module will adjust to the current input range of "input" and re-map the value into N bits value and broadcast it to "output" port. When "calibrate" is false, this module will not adjust to the current input range, but keep re-map the value by using the current lower and upper value. If the N bits value comes in from the "feedback" port, this module will map it back to the input range (the reverse mapping). The "lower", "upper" input and output ports are for two way communication to external integer objects. So the value will keep consist when user modify the "lower" and "upper" value by property dialog box.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF). "fraction" set the current blank display area (on the top and bottom of display area) in percent. percent. For example, fraction=0 will use all display area, fraction=25 will have 25% blank area on the top and bottom of display area. "upper" and "lower" set the current input range set.
Name: AvgFilterObj
Input: "input" on the left edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: When event comes into "input" port, this module will calculate the average value of last N input value (include the current value) and broadcast the value through the "output" port. Basically, it works as a low-pass filter.
Properties: "moduleColor" set the background color. "N" set the number of contiguous input values to average.
Name: DelaySustainObj
Input: "input" on the left edge with maximum one connection. "sampling-clock", "delay", and "sustain" on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections. "delay" and "sustain" on the bottom edge with unlimited connections.
Function: When there is a raise (false to true) event detected in "input" port, this module will delay the input value for "delay" ticks (Tick marks come from sampling-clock). When there is drop (true to false) event detected in "input" port, this module will sustain last value for "sustain" ticks. The "delay", "sustain" input and output ports are for two way communication to external integer objects. So the value will keep consist when user modify the "delay" and "sustain" value by property dialog box.
Properties: "moduleColor" set the background color. "delay" set the number of delay ticks. "sustain" set the number of sustain ticks.
Name: RtoIObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Convert the "input" port's real number into integer (with rounding) and broadcast the result to "output" port.
Properties: "moduleColor" set the background color.
Name: ItoRObj
Input: "input" integer port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Convert the "input" port's integer into real number and broadcast the result to "output" port.
Properties: "moduleColor" set the background color.
Name: RGreaterThanObj
Input: "input-1" real number port on the left edge and "input-2" real number port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Compare the value of "input-1" and "input-2" and broadcast the result value to "output" port when receiving an input event. Result value is true when "input-1" is larger "input-2", false otherwise.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical operation (true=1, false=0). When it is 16, it will become the 16 bit operation (true=0xFFFF, false=0x0000).
Name: RGreaterEqualObj
Input: "input-1" real number port on the left edge and "input-2" real number port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Compare the value of "input-1" and "input-2" and broadcast the result value to "output" port when receiving an input event. Result value is true when "input-1" is greater or equal "input-2", false otherwise.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical operation (true=1, false=0). When it is 16, it will become the 16 bit operation (true=0xFFFF, false=0x0000).
Name: REqualObj
Input: "input-1" real number port on the left edge and "input-2" real number port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Compare the value of "input-1" and "input-2" and broadcast the result value to "output" port when receiving an input event. Result value is true when "input-1" is equal "input-2", false otherwise.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical operation (true=1, false=0). When it is 16, it will become the 16 bit operation (true=0xFFFF, false=0x0000).
Name: RNotEqualObj
Input: "input-1" real number port on the left edge and "input-2" real number port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Compare the value of "input-1" and "input-2" and broadcast the result value to "output" port when receiving an input event. Result value is true when "input-1" is not equal "input-2", false otherwise.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it become the logical operation (true=1, false=0). When it is 16, it will become the 16 bit operation (true=0xFFFF, false=0x0000).
Name: RAddObj
Input: "input" real number port on the real number edge with unlimited connections.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate the sum of all the input values and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RMultiplyObj
Input: "input" real number port on the left edge with unlimited connections.
Output: "output" real number port on the right edge with unlimited connections.
Function: Multiply all the input values and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RSubstractObj
Input: "input-1" real number port on the left edge and "input-2" real number port on the top edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate "input-1" - "input-1" and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RDivideObj
Input: "input-1" real port on the left edge and "input-2" real port on the top edge with maximum one connection.
Output: "output" real port on the right edge with unlimited connections.
Function: Calculate "input-1" / "input-2" and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RAbsObj
Input: "input" real number port on the left with maximum one connections.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate ABS("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RPowObj
Input: "input-1" real number port on the left edge and "input-2" real number port on the top edge with maximum one connection.
Output: "output" integer port on the right edge with unlimited connections.
Function: Calculate "input-1" ^ "input-2" and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RMaxObj
Input: "input" real number port on the left edge with unlimited connections.
Output: "output" real number port on the right edge with unlimited connections.
Function: Choose the maximum input value and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RMinObj
Input: "input" real number port on the left edge with unlimited connections.
Output: "output" real number port on the right edge with unlimited connections.
Function: Choose the minimum input value and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RSinObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate SIN("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RCosObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate COS("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RASinObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate ASIN("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RACosObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate ACOS("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RTanObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate TAN("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RATanObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate ATAN("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RExpObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate EXP("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RLogObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate LOG("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RSqrtObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate SQRT("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RRoundObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate ROUND("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RCeilObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate CEIL("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RFloorObj
Input: "input" real number port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate FLOOR("input") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RModObj
Input: "input-1" real number port on the left edge and "input-2" real number port on the top edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate the reminder of "input-1"/"input-2" and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RATan2Obj
Input: "input-1" real number port on the left edge and "input-2" real number port on the top edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: Calculate ATAN2("input-1", "input-2") and broadcast the result value to "output" port when receiving an input event.
Properties: "moduleColor" set the background color.
Name: RPIObj
Input: None.
Output: "output" real number port on the right edge with unlimited connections.
Function: Return PI value when requested.
Properties: "moduleColor" set the background color.
Name: REObj
Input: None.
Output: "output" real number port on the right edge with unlimited connections.
Function: Return e value when requested.
Properties: "moduleColor" set the background color.
Name: RRandomObj
Input: "control(logical)" integer port on the left edge with maximum one connection.
Output: "output" real number port on the right edge with unlimited connections.
Function: When detect a raise signal (from false to true) on the "control" port, this module will prepare a real random number (0-1.0) and broadcast the value to "output" port.
Properties: "moduleColor" set the background color.
Name: RCalibrateObj
Input: "calibrate(logical)" integer, "lower" and "upper" real number port on the top edge and "input" real number, "feedback" integer port on the left edge with maximum one connection.
Output: "output" integer and "decalibrate" real number port on the right edge and "lower", "upper" real number port on the bottom edge with unlimited connections.
Function: When "calibrate" is true, this module will adjust to the current input range of "input" and re-map the value into N bits integer value and broadcast it to "output" port. When "calibrate" is false, this module will not adjust to the current input range, but keep re-map the value by using the current lower and upper value. If the N bits value comes in from the "feedback" port, this module will map it back to the input range (the reverse mapping). The "lower", "upper" input and output ports are for two way communication to external integer objects. So the value will keep consist when user modify the "lower" and "upper" value by property dialog box.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF). "fraction" set the current blank display area (on the top and bottom of display area) in percent. percent. For example, fraction=0 will use all display area, fraction=25 will have 25% blank area on the top and bottom of display area. "upper" and "lower" set the current input range set.
Name: SKeyboardObj
Input: "input" string port on the left edge with maximum one connection.
Output: "output" string number port on the right edge with unlimited connections.
Function: This module will generate string event with exact one character when user press a key. It works even NeatTools is minimized or in the background. If user supply a string event into the "input" port, it will simulate the keyboard event (just like someone is typing the keyboard) to the windows system. This function will only work when NeatTools is in background to avoid feedback problems.
Properties: "moduleColor" set the background color.
etc.Name: KeyboardObj
Input: "stroke(logical)" integer port on the left edge and "depress(logical)" integer port on the top edge with maximum one connection.
Output: "output" string number port on the right edge with unlimited connections.
Function: This module will generate integer event when a key that match this module pressed. It works even NeatTools is minimized or in the background. If user supply a true integer event into the "stroke(logical)" port, it will simulate a stroke keyboard event (just like someone press and then release the key) to the windows system. If user supply a raise integer event (from false to true ) into the "depress(logical)" port, it will simulate a depress keyboard event (just like someone press the key) to the windows system. If user supply a drop integer event (from true to false) into the "depress(logical)" port, it will simulate a release keyboard event (just like someone release the key) to the windows system. These functions will only work when NeatTools is in background to avoid feedback problems.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF).
Name: MixerObj
Input: "input-L/Mono" integer port on the left edge and "input-R" integer port on the top edge with maximum one connection.
Output: "output-L/Mono" integer port on the right edge and "output-R" integer port on the bottom edge with unlimited connections.
Function: This module is designed to couple the windows' multimedia control components. The "Output Volume" module will accept mono or stereo input value to change the volume level of a sound source. It also will feedback with output value that indicate the volume level of a particular sound source. It will couple the exist mixer applications. So when user change the level value in other mixer application, this module will reflect the change by send out events from output ports. When the module show gray text, it indicate that your system does not support this type of sound source.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF).
Name: MixerObj
Input: "input " integer port on the left edge with maximum one connection.
Output: "output" integer port on the bottom edge with unlimited connections.
Function: This module is designed to couple the windows' multimedia control components. The "Output Mute" module will accept input value to change the state (Mute or not) of a sound source. It also will feedback with output value that indicate the state of a particular sound source. It will couple the exist mixer applications. So when user change the state of a sound source in other mixer application, this module will reflect the change by send out events from output port. When the module show gray text, it indicate that your system does not support this type of sound source.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF).
Name: MixerObj
Input: "input-L/Mono" integer port on the left edge and "input-R" integer port on the top edge with maximum one connection.
Output: "output-L/Mono" integer port on the right edge and "output-R" integer port on the bottom edge with unlimited connections.
Function: This module is designed to couple the windows' multimedia control components. The "Input Volume" module will accept mono or stereo input value to change the recording level of a sound source. It also will feedback with output value that indicate the recording level of a particular sound source. It will couple the exist mixer applications. So when user change the level value in other mixer application, this module will reflect the change by send out events from output ports. When the module show gray text, it indicate that your system does not support this type of sound source for recording.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF).
Name: MixerObj
Input: "input " integer port on the left edge with maximum one connection.
Output: "output" integer port on the bottom edge with unlimited connections.
Function: This module is designed to couple the windows' multimedia control components. The "Input Mute" module will accept input value to change the state (Mute or not) of a sound source's recording. It also will feedback with output value that indicate the state of a particular sound source's recording. It will couple the exist mixer applications. So when user change the state of a sound source in other mixer application, this module will reflect the change by send out events from output port. When the module show gray text, it indicate that your system does not support this type of sound source's mute operation.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF).
Name: MIDIOutObj
Input: "input" MIDI port on the left edge and "enabled(logical)" integer port on the top edge with maximum one connection.
Output: None.
Function: When "enabled" is true, this module will open the assigned MIDI device and start to wait for MIDI event coming from the "input" port. When receive a MIDI event, this module will transfer it into the assigned and opened MIDI device.
Properties: "moduleColor" set the background color. "device" set the destination MIDI device. Depend on windows' setting. It could be internal FM or external MIDI port. If it is internal FM, send in MIDI events will generate sound. If it is external MIDI port, send in MIDI events could control external MIDI instrument which connected to this hardware MIDI port.
Name: MIDIInObj
Input: "enabled(logical)" integer port on the top edge with maximum one connection.
Output: "output" MIDI port on the right edge with unlimited connections.
Function: When "enabled" is true, this module will open the assigned MIDI device and start to send out MIDI events (which coming from the hardware MIDI port or the internal MIDI device) to the "output" port.
Properties: "moduleColor" set the background color. "device" set the destination MIDI device. Depend on windows' setting. It could be internal MIDI devise or external MIDI port. If it is external MIDI port, play notes or playback on external MIDI instrument will send in MIDI events and broadcast through "output" port.
Name: MIDIObj
Input: "midi-in" MIDI port on the top edge with maximum one connection. 127 notes inputs (from "Octave[0] C" to "Octave[10]G"), "channel(0-15)", "channel_pressure", "program(0-127)", "volume", "pan", "damper" and "pitch" integer port on the left edge with maximum one connection.
Output: "midi-out" MIDI port on the bottom edge with unlimited connections. 127 notes outputs (from "Octave[0] C" to "Octave[10]G"), "channel(0-15)", "channel_pressure", "program(0-127)", "volume", "pan", "damper" and "pitch" integer port on the right edge with unlimited connections.
Function: In order to generate MIDI event from integer event, user can use this module to create almost all type of MIDI events. When receive a MIDI event through "midi-in" port, this module will decompose the MIDI event into integer event into the related output ports.
Properties: "moduleColor" set the background color. "N Bits" set the operation width. When it is one, it will generate only logical (1-bit) value (true, or false). When it is 16, it will generate the 16 bit wise value (from 0 to 0xFFFF).
Name: MIDIChannelObj
Input: "midi-in" MIDI port on the top edge with maximum one connection. "ch1-in", "ch2-in", ..., "ch15-in", and "misc-in" MIDI port on the left edge with maximum one connection.
Output: "midi-out" MIDI port on the bottom edge with unlimited connections. "ch1-out", "ch2-out", ..., "ch15-out", and "misc-out" MIDI port on the right edge with unlimited connections.
Function: There are 16 channel in the MIDI signal. When receive MIDI event from the "midi-in" port, this module can separate the event into the correspond output channel port. If user want a MIDI event change to anther channel, he can feed the MIDI event to say the "ch1-in" port. Then the even coming out from the "midi-out" port will have MIDI signal with channel 1 assigned.
Properties: "moduleColor" set the background color.
Name: MIDIFileObj
Input: "record(logical)" integer, "play(logical)" integer, "pause(logical)" integer, "filename" string, "sequence" integer, "pos" integer, "N(1-128)" integer, and "ratio" integer port on the top edge with maximum one connection. There are MIDI ports (name and number of the MIDI ports determined by MIDI file user assigned) on the left edge with maximum one connection.
Output: "count", "total", and "tempo" integer port on the bottom edge with unlimited connections. There are MIDI ports (name and number of the MIDI ports determined by MIDI file user assigned) on the right edge with unlimited connections.
Function: This module could load in a MIDI file with "MID" extension and play it back or recording(Recording portion is not complete yet). When "record(logical)" receive a raise event (from false to true), it will start to recording MIDI events into assigned file. When "play(logical)" receive a raise event, it will start to play back the content of the current MIDI file. When "pause" is true, it will pause the current recording or playback action. The "filename" and "sequence" combine could use to assign the MIDI filename. When "sequence" is zero, the "filename" is the assigned filename. If "sequence" not equal to zero, say 1, the assigned filename will become "filename_1". Just change the sequence number and user could record on sequences of different files. The "pos" is the current begin event count. So user could playback from any starting position. The "N" set the
Properties: "moduleColor" set the background color.
+-JObject
|
+-JClipboard
|
+-JColor
|
+-JDimension
|
+-JEvent
|
+-JFontMetrics
|
+-JInsets
|
+-JLayoutManager
| |
| +-JBorderLayout
| |
| +-JFlowLayout
| |
| +-JGridLayout
|
+-JPoint
| |
| +-JRect
| |
| +-JComponent
| |
| +-JCanvas
| | |
| | +-JLabel
| | | |
| | | +-JButton
| | | | |
| | | | +-JPushButton
| | | | | |
| | | | | +-JThumb
| | | | | |
| | | | | +-JTriangleButton
| | | | |
| | | | +-JToggleButton
| | | | |
| | | | +-JModuleButton
| | | |
| | | +-JTextField
| | |
| | +-JListBox
| | |
| | +-JRuler
| | |
| | +-JScroller
| | |
| | +-JSeparator
| | |
| | +-JAbout
| | |
| | +-JModuleCanvas
| |
| +-JDialog
| |
| +-JModal
| | |
| | +-JMessageBox
| | |
| | +-JColorBox
| | |
| | +-JInputBox
| | | |
| | | +-JFileBox
| | | |
| | | +-JIntegerBox
| | |
| | +-JIntegerListBox
| | |
| | +-JPropertyBox
| |
| +-JPanel
| |
| +-JWindow
|
+-JBlockInputStream
|
+-JBlockOutputStream
|
+-JFile
|
+-JFilterInputStream
| |
| +-JBufferedInputStream
|
+-JFilterOutputStream
| |
| +-JBufferedOutputStream
|
+-JPipedStream
|
+-JBoolean
|
+-JCharacter
|
+-JDouble
|
+-JFloat
|
+-JInteger
|
+-JLong
|
+-JMath
|
+-JPObject
| |
| +-JObjectPtr
|
+-JReference
| |
| +-JFont
| |
| +-JGraphics
| |
| +-JImage
| |
| +-JRegion
| |
| +-JBlock
| |
| +-JCriticalSection
| |
| +-JDescriptor
| | |
| | +-JColor
| | |
| | +-JFileInputStream
| | | |
| | | +-JFileIOStream
| | |
| | +-JFileOutputStream
| | |
| | +-JSocket
| | | |
| | | +-JServerSocket
| | |
| | +-JSocketInputStream
| | |
| | +-JSocketOutputStream
| |
| +-JProcess
| |
| +-JString
| |
| +-JThread
| |
| +-JArray
| |
| +-JList
| |
| +-JDList
|
+-JSystem
|
+-JThrowable
| |
| +-JError
| |
| +-JException
| |
| +-JIOException
| | |
| | +-JEOFException
| | |
| | +-JInterruptedIOException
| | |
| | +-JClassReferenceException
| | |
| | +-JSocketException
| | |
| | +-JUnknownHostException
| |
| +-JRuntimeException
| |
| +-JArithmeticException
| |
| +-JIllegalArgumentException
| |
| +-JNullPointerException
| |
| +-JProcessCreateException
| |
| +-JThreadCreateException
|
+-JDataType
| |
| +-JBlockData
| | |
| | +-JBytesData
| | |
| | +-JVideoData
| | |
| | +-JWaveData
| |
| +-JIntegerData
| | |
| | +-JColorData
| | |
| | +-JDateData
| | |
| | +-JMIDIData
| |
| +-JRealData
| |
| +-JStringData
|
+-JFDimension
|
+-JFPoint
| |
| +-JFRect
| |
| +-JViewObj
| |
| +-JGuideObj
| |
| +-JLineObj
| |
| +-JModuleObj
| | |
| | +-JColorObj
| | |
| | +-JLEDObj
| | | |
| | | +-JLabelObj
| | | | |
| | | | +-JDateObj
| | | | |
| | | | +-JIntegerObj
| | | | |
| | | | +-JRealObj
| | | |
| | | +-JNBitsObj
| | | |
| | | +-J1DMeterObj
| | | | |
| | | | +-J1DViewerObj
| | | |
| | | +-J2DMeterObj
| | | |
| | | +-JBtnObj
| | | |
| | | +-J1DSliderObj
| | | |
| | | +-J2DSliderObj
| | | |
| | | +-JFocusObj
| | | |
| | | +-JPushBtnObj
| | | |
| | | +-JSwitchObj
| | |
| | +-JRAddObj
| | | |
| | | +-JRAbsObj
| | | | |
| | | | +-JItoRObj
| | | | |
| | | | +-JRACosObj
| | | | |
| | | | +-JRASinObj
| | | | |
| | | | +-JRATanObj
| | | | |
| | | | +-JRCeilObj
| | | | |
| | | | +-JRCosObj
| | | | |
| | | | +-JRDivideObj
| | | | | |
| | | | | +-JRAtan2Obj
| | | | | |
| | | | | +-JRModObj
| | | | | |
| | | | | +-JRPowObj
| | | | | |
| | | | | +-JRSubtractObj
| | | | |
| | | | +-JRExpObj
| | | | |
| | | | +-JRFloorObj
| | | | |
| | | | +-JRLogObj
| | | | |
| | | | +-JRRandomObj
| | | | |
| | | | +-JRRoundObj
| | | | |
| | | | +-JRSinObj
| | | | |
| | | | +-JRSqrtObj
| | | | |
| | | | +-JRTanObj
| | | | |
| | | | +-JRtoIObj
| | | |
| | | +-JRMaxObj
| | | |
| | | +-JRMinObj
| | | |
| | | +-JRMultiplyObj
| | | |
| | | +-JRPIObj
| | | |
| | | +-JREObj
| | |
| | +-JTimeObj
| | |
| | +-JAddObj
| | |
| | +-JAbsObj
| | | |
| | | +-JDelayObj
| | | |
| | | +-JDivideObj
| | | | |
| | | | +-JAccumulatorObj
| | | | |
| | | | +-JPowObj
| | | | |
| | | | +-JRemainObj
| | | | |
| | | | +-JSubtractObj
| | | |
| | | +-JNodeObj
| | |
| | +-JAvgFilterObj
| | |
| | +-JBtoIObj
| | |
| | +-JCOMObj
| | |
| | +-JComplexObj
| | |
| | +-JConvertObj
| | |
| | +-JDataBaseObj
| | |
| | +-JDaviconObj
| | |
| | +-JDeMultiplexerObj
| | |
| | +-JDecoderObj
| | |
| | +-JDelaySustainObj
| | |
| | +-JEncoderObj
| | |
| | +-JExclusiveObj
| | |
| | +-JItoBObj
| | |
| | +-JLPTObj
| | |
| | +-JMIDIChannelObj
| | |
| | +-JMIDIOutObj
| | | |
| | | +-JMIDIInObj
| | |
| | +-JMaxObj
| | |
| | +-JMinObj
| | |
| | +-JMultiplexerObj
| | |
| | +-JMultiplyObj
| | |
| | +-JRecorderObj
| | | |
| | | +-JMIDIFileObj
| | | | |
| | | | +-JRMIDFileObj
| | | |
| | | +-JWaveFileObj
| | |
| | +-JSampleObj
| | | |
| | | +-JControlObj
| | |
| | +-JSocketObj
| | | |
| | | +-JServerSocketObj
| | |
| | +-JWaveOutObj
| | | |
| | | +-JWaveInObj
| | |
| | +-JANDObj
| | |
| | +-JCalibrateObj
| | |
| | +-JClockDividerObj
| | |
| | +-JJoyStickObj
| | |
| | +-JMIDIObj
| | |
| | +-JMixerObj
| | |
| | +-JNOTObj
| | | |
| | | +-JCHObj
| | | |
| | | +-JDGreaterThanObj
| | | | |
| | | | +-JDEqualObj
| | | | |
| | | | +-JDGreaterEqualObj
| | | | |
| | | | +-JDNotEqualObj
| | | |
| | | +-JGreaterThanObj
| | | | |
| | | | +-JEqualObj
| | | | |
| | | | +-JGreaterEqualObj
| | | | |
| | | | +-JNotEqualObj
| | | |
| | | +-JKeyboardObj
| | | |
| | | +-JMouseBtnObj
| | | | |
| | | | +-JMousePosObj
| | | |
| | | +-JMouseObj
| | | |
| | | +-JPulseObj
| | | |
| | | +-JRGreaterThanObj
| | | | |
| | | | +-JREqualObj
| | | | |
| | | | +-JRGreaterEqualObj
| | | | |
| | | | +-JRNotEqualObj
| | | |
| | | +-JRandomObj
| | | |
| | | +-JSGreaterThanObj
| | | |
| | | +-JSEqualObj
| | | |
| | | +-JSGreaterEqualObj
| | | |
| | | +-JSNotEqualObj
| | |
| | +-JORObj
| | |
| | +-JOxfordObj
| | |
| | +-JRCalibrateObj
| | |
| | +-JTNGObj
| | | |
| | | +-JTNG3Obj
| | |
| | +-JTimerObj
| | |
| | +-JXORObj
| |
| +-JViewSet
| |
| +-JFocusSet
| |
| +-JLinkObj
|
+-JProperty
| |
| +-JColorProperty
| |
| +-JIntegerListProperty
| |
| +-JIntegerProperty
| |
| +-JRealProperty
| |
| +-JStringProperty
| |
| +-JFileProperty
|
+-JInetAddress
|
+-JAssociation
|
+-JDataBase
|
+-JDate
|
+-JFileArray
|
+-JHashTable
| |
| +-JDictionary
|
+-JRandom
The NeatTools architecture defines the complete structure for implementing NeatTools' cross-platform, extensive module unit, usability, and functionality features by using UML (Unified Modeling Language).
The NeatTools' implementation model is defined as a three-layer architecture. This architecture is necessary for cross-platform design. There are several advantages associated with this approach:
The conceptual framework for NeatTools is based on an architecture with three layers:
Functions of the layers are summarized in the following table:
Layer |
Description |
Operating system and programming language |
the service and resources provided by operation systems and programming language itself. |
Java like cross-platform API |
a set of abstract classes that provide the windows and basic service for application construction needs. |
NeatTools application |
provides the actual implementation of usability and functionality which meet the general requirement as a real-time visual programming tool. |
The operating system and programming language layer provide all the basic system service and resources. This layer includes Win32 API, X11 API, and C++ run time library. The Win32 API and X11 API provide the generally required functionality of windowing, graphics context, objects and memory management in a platform dependent fashion. The C++ run time usually comes with the actual compiler implementations. There are even some standards proposed for the C++ language itself. However, there are still some significant differences between companies and platforms. Hence, it is desirable to have an abstract layer which provides standardized interfacing between the application layer and the operating system layer.
The Java-like cross platform API layer is the abstract layer that works between the operating system and the application. It releases the application's dependency on the operating system and provides a higher level utility class object support. Usually, the API is a collection of procedures. It is usually very difficult for a programmer to: find out the relevant procedures in an API; know its capability and usage; know how it interacts with other procedures; not to mention putting them together in order to accomplish a required task. In this sense, a cross-platform API layer is necessary and desirable.
Now comes the second question: why Java-like. "Java-like" means it defines the class and interface according to a Java API specification. NeatTools needs to be fast and efficient to handle the real-time and computationally intensive task (s). By implementing a Java-like API in C++, we gain Java’s ability to run on different platforms as well as the high performance of C++. The application layer is where we build the actual NeatTools implementation in cross platform fashion. Different applications will eventually need some special classes which could perform the usability and functionality needed for the particular applications. So the presence of this layer is natural.
The NeatTools implementation is moderately complex. It is composed of approximately 100 classes in a Java-like cross platform API layer and approximately 120 classes in a NeatTools application layer. The complexity of the classes is managed by organizing them into logical packages. The NeatTools implementation is decomposed into the top-level packages shown in Figure 1:
The Operating system and C++ runtime package is further decomposed as show in Figure 2:
Figure 2: OS and C++ runtime layer
The Java-like cross platform package is further decomposed into NET, AWT, UTIL, IO, and LANG packages as show in Figure 3:
Figure 3: Java like cross-platform API layer
Figure 4: Exceptions class diagram in Java like API layer
The LANG package contains the classes that make up the core of the Java-like API layer. The classes of the LANG package are summarized in the following table:
Class |
Description |
JBlock |
Memory block class |
JBoolean |
Object wrapper for Boolean values |
JCharacter |
Object wrapper for char values |
JCriticalSection |
Exclusive object for critical section |
JDescriptor |
Generic descriptor manipulate object |
JDouble |
Object wrapper for double values |
JFloat |
Object wrapper for float values |
JInteger |
Object wrapper for integer values |
JLong |
Object wrapper for long values |
JMath |
Object wrapper for math functions |
JObject |
Generic object class, at top of inheritance hierarchy |
JObjectPtr |
Object wrapper for object pointer |
JPObject |
Object wrapper for object reference |
JProcess |
Generic behavior for process |
JReference |
Generic handle manipulate object |
JString |
Character strings |
JThread |
Class for managing threads |
JThrowable |
Generic exception class; all object thrown must be a Throwable |
Table 2: Classes of LANG package
The UTIL package contains various utility classes, including random numbers, system properties, and other useful classes. Classes of the UTIL package are summarized in the following table:
Class |
Description |
JArray |
A array of objects |
JAssociation |
Association object that associate two objects |
JDList |
A double link list |
JDictionary |
A class that maps between keys and values |
JFileArray |
A massive array that store content in file system |
JHashTable |
A hash table |
JList |
A link list |
JRandom |
A random number generator object |
Table 3: Classes of UTIL package
The IO package provides input and output classes and classes for streams and files. The classes of IO packages are summarized in the following table:
Class |
Description |
JBlockInputStream |
An input stream from a memory block |
JBlockOutputStream |
An output stream from a memory block |
JBufferedInputStream |
A buffered input stream |
JBufferedOutputStream |
A buffered output stream |
JFile |
Represents a file on the file system |
JFileIOStream |
A input/output stream from and to a file |
JFileInputStream |
An input stream from a file |
JFileOutputStream |
An output stream to a file |
JFilterInputStream |
A class which provides a filter for input stream |
JFilterOutputStream |
A class which provides a filter for output stream |
JInputStream |
An abstract class representing an input stream |
JOutputStream |
An abstract class representing an output stream |
JPipedStream |
An piped input/output stream |
Table 4: Classes of IO package
The NET package contains classes for performing network operations, such as sockets and URLs. Classes of the NET package are summarized in the following table:
Class |
Description |
JInetAddress |
An object representation of an Internet host |
JServerSocket |
A server-side socket |
JSocket |
A socket |
JSocketInputStream |
An input stream from a socket connection |
JSocketOutputStream |
An output stream to a socket connection |
Table 5: Classes of NET package
The AWT package contains the classes that make up the Abstract Windowing Toolkit. This package contains the window abstraction and graphics abstraction related classes. The classes of AWT package are summarized in the following table:
Class |
Description |
JBorderLayout |
A layout manager for arranging items in border formation |
JButton |
A UI button |
JCanvas |
A canvas for drawing and performing other graphics operation |
JClipboard |
An object wrapper for clipboard buffer |
JColor |
A representation of a color |
JColorBox |
A dialog box that could change color setting |
JComponent |
The generic class for all UI components |
JDialog |
A window for brief interactions with users |
JDimension |
width and height |
JEvent |
An object representing events caused by the system or based on user input |
JFileBox |
A dialog box that could select a file in file system |
JFlowLayout |
A layout manager that lays out objects from left to right in rows |
JFont |
A representation of a font |
JFontMetrics |
A class for holding information about a specific font's character information |
JGraphics |
The generic behavior for representing a graphics context, and for drawing and painting shapes and objects |
JGridLayout |
A layout manager with rows and columns; elements are added to each cell in the grid |
JImage |
A representation of a bitmap image |
JInputBox |
A dialog box for input text |
JInsets |
Distances from the outer border of the window; used to layout components |
JIntegerBox |
A dialog box for input integer values |
JIntegerListBox |
A dialog box for select integer values |
JLabel |
A text label for UI components |
JLayoutManager |
A generic class for all layout manager |
JListBox |
A scrolling list |
JMessageBox |
A dialog box that display a message to users |
JModal |
A specialized dialog box that will interact with users |
JPanel |
A container that is displayed |
JPoint |
x and y coordinates |
JPushButton |
A UI pushbutton |
JRect |
x and y coordinates for the top corner, plus width and height |
JRegion |
A logical region defined in graphics context |
JRuler |
A UI ruler |
JScroller |
A UI scrollbar |
JSeparator |
A UI separator |
JTextField |
A fixed-size editable text field |
JThumb |
A UI thumb in scrollbar |
JToggleButton |
A UI toggle button |
JTriangleButton |
A UI triangle button in scrollbar |
JWindow |
A top-level window |
Table 6: Classes of AWT package
The NeatTools application package is further decomposed into NEAT, DESKTOP, Modules, and External Modules packages as show in Figure 5:
Figure 5: NeatTools application layer
Figure 5: Property in NEAT package
Figure 7: NEAT package (continue)
The NeatTools modules could define internal properties which could be modified through a property dialog box. Each property will become an item in a property list box. A user could select and modify them. Taking advantage of the object oriented programming technique, the Property class becomes the generic property representation. And all other properties will be derived from Property class and will benefit the unified process and editing procedures.
Just as the LANG package is the core of Java-like API layer, the NEAT package is the core of the NeatTools application layer. It defines the basic object structure of how JViewObj aggregates into JVewSet. It also defines the basic module behavior which includes input group and output group (an aggregation of JFocusSet. Here, JFocusSet is the composition of JLinkObj that represents the input and output links of a module object). Because of the polymorph feature of object orient programming, the JViewSet could become the composition of any object which derived from JVewObj. This structure forms a container-component relationship pattern.
The classes of NEAT package are summarized in the following table:
Class |
Description |
JANDObj |
A NeatTools module that handle AND operation |
JAbout |
A banner that shows the NeatTools |
JColorProperty |
A property that represent color values |
JFDimension |
width and height in floating point format |
JFPoint |
x and y in floating point format |
JFRect |
A rectangle in floating point format |
JFileProperty |
A property that represent files |
JFocusSet |
A composition of JViewObj reference |
JGuideObj |
A guide line in NeatTools desktop area |
JIntegerListProperty |
A property that represent a list of integer values |
JIntegerProperty |
A property that represent integer values |
JLineObj |
A line representation in NeatTools desktop area |
JLinkObj |
A link between two NeatTools modules |
JModuleButton |
A UI button that display NeatTools modules |
JModuleCanvas |
A UI canvas that display NeatTools modules |
JModuleObj |
A generic class of all NeatTools modules |
JProperty |
A generic class of all properties |
JPropertyBox |
A dialog box that could change the property settings |
JRealProperty |
A property that represent the floating point values |
JStringProperty |
A property that represent the string values |
JViewObj |
A generic class of all display object in NeatTools desktop area |
JViewSet |
A composition of JViewObj objects |
Table 7: Classes of NEAT package
All NeatTools modules are derived directly or indirectly from JModuleObj. Currently, there are around 100 different modules in NeatTools. Each modules works like a black box, or Ics, which could handle one or several functions in a particular field. As AND module is the AND gate in digital logic, OR module is the OR gate in digital logic. Please see section 3 for more detailed information on NeatTools module structure.
The external modules are just like a normal NeatTools module. The only difference is how it is complied and linked into the system. Follow the special instructions in "NeatTools external module development kit" and it will guide you through the creation of an external module and into a dynamic linkage library (DLL). NeatTools will load the external modules in startup when it can locate them in the NeatTools directory. Or they could be loaded in runtime by pressing "Load Module" button in NeatTools. If an external module is used in a NeatTools network and the module was not loaded in memory yet, NeatTools will popup a dialog box for the user to specify the location of the particular external module.
The DESKTOP package contains a very complex class called JView which is a UI canvas as well as the NeatTools desktop area. It contains the aggregation and composition of all the NeatTools modules, links between modules, guide lines, and focus objects selected by users. It also handles all the user and system events, such as mouse events, keyboard events, and system notify events. It represents and implements
By using module abstraction, I simplify the module event broadcast model into a process involve only three methods and directly function call between these methods. There three method include engine, broadcast, and access. Usually, programmer will have to override engine and access method to define the module's behavior. The behavior here means how module react to external events and change its internal state to respond to the event. Also, some module could change its state or broadcast message without external trigger by using its own thread.
How those three method methods work together ? and how NeatTools system involve in the process ? First, I have to mansion the Link Object which NeatTools use to record the logical connection between modules. The object defined as follow (Programmer always could find all the header files under http://www.pulsar.org/ej/work/oop/oop.html :
class
JLinkObj : public JViewSet {
...
public:
...
JLinkObj();
...
void access(const JDataType& data);
void engine();
...
JModuleObj *from, *to;
int fn, tn;
};
In this object, I defined the public data member include the Module pointer 'from' and 'to', and Interger 'fn' and 'tn'. Pointer 'from' reference the source module and Pointer 'to' reference the destination module. 'fn' stand for the output port number of the source module and 'tn' stand for the input port number of the destination module. In NeatTools module, programmer can define the number of input or output by fixed number or dynamically change the number of input or output port. Each port could accept one or more connections depend on the behavior of module. I will discuss that later on. So what happen when user make connection between two modules ? NeatTools will initiate a link and put it in a link list of links and then each module on the particular port will have separate link list which has the reference to the link itself. (for performance reason, so module could direct access to the link object without search).
Now, lets get back to the broadcast model again. Module programmer could decide to broadcast event on a particular port at any time. It could happen in its thread loop or just respond to incoming event from other modules. When broadcast(fn) is been called, NeatTools will invoke all the connected module's engine(tn, link). When a module's engine method got invoked, it knows an event occur and it comes from which module, which output port, and it goes into which input port by access the data member of the link parameter. When programmer implement the engine method, he will first use tn to identify which input port got event and then use link.access(data) to access the event content. the link.access(data) will translate into call source module's access(fn, link, data) method. So before call broadcast, programmer should prepare the value in data member so when the destination module call its access method, it could provide the value right on time. Why, we have this trouble to have the engine call the access in order to get the data ? Because, in some situation, like AND gate, its input port could accept any number of connections. And when an event occur through one of the connection, the AND has to go through all the input connection to figure out the result value. In this case, The AND gate call module's access even when that module did not call broadcast. So, programmer should keep it in mind that access should always provide current value.
In order to see how it works, let see a simple example on a module which calculate X2 as an output when integer event going in. We will just focus on the broadcast related methods at this time.
// JSquareObj.h
class JSquareObj : public JModuleObj {
protected:
virtual void writeContent(class JOutputStream& os);
virtual void readContent(class JDictionary& dict);
public:
virtual const char* className() const;
virtual JObject* clone() const;
JSquareObj();
virtual void draw(JGraphics g, int x, int y, int w, int h);
virtual void access(int n, JLinkObj& link, const JDataType& data);
virtual boolean inputAllowed(int n);
virtual boolean outputAllowed(int n);
virtual void engine(int n, JLinkObj& link);
protected:
int value;
};
#include "JSquareObj.h"
#include "JLinkObj.h"
#include "JIntegerData.h"
char* theJSquareObj = JSquareObj().Register();
void JSqureObj::writeContent(JOutputStream& os) {
JModuleObj::writeContent(os);
putInteger(os, "value", value);
}
void JSquareObj::readContent(JDictionary& dict) {
JModuleObj::readContent(dict);
value = getInteger(dict, "value");
}
const char* JSquareObj::className() const { return "JSquareObj";}
JObject* JSquareObj::clone() const { return new JSquareObj(*this);}
JSquareObj::JSquareObj() { igm = 1; value = 0;}
void JSquareObj::draw(JGraphics g, int x, int y, int w, int h) {
JRect rect(x, y, w, h);
drawText(g, JString("Sqr"), rect);
}
void JSquareObj::access(int n, JLinkObj& link, const JDataType& data) { INT(data) = value;}
boolean JSquareObj::inputAllowed(int n)
{ return !inputSet(n).last();}
boolean JSquareObj::outputAllowed(int n) { return true;}
void JSquareObj::engine(int n, JLinkObj& link) {
int nv;
link.access(JIntegerData(nv));
nv *= nv;
if (value != nv) {
value = nv;
broadcast(0);
}
}
Here, we start our focus on engine method. In this method, we declare a temporary integer variable nv. the link.access(JIntegerData(nv)) will first create JIntegerData (a derived class of JDataType) instance and use it as a media to transfer integer value into nv. Every data type are derived class of JDataType. I will discuss the data type polymorphism later. Because of polymorphism, we can use the same access method to transfer all kind of different data type. After this statement, the input value will assign on variable nv. So we calculate the square of nv. If nv and value are different, we update the value and call broadcast(0). Here we only have one output port, so the only valid broadcast number would be zero. When process broadcast method, the destination module's engine method will get invoked and eventually it will call source module's access method. Here, in access method, we have only one statement: INT(data) = value. INT is a macro defined in JIntegerData.h to type cast JIntegerData into int&. So we can use it and assign new value. Programmer also could use data.assign(JInteger(value)). JInteger is a wrapper class for int data (Like the Integer class in Java). But the first implementation is faster.
Almost every object class in NeatTools are subclass of JObject directly or indirectly. There are some method which always need to be take care of or override to ensure the basic object behavior works correctly.
In the previous example module, after invoke some header files, you will see a strange line :
char* theJSquareObj = JSquareObj().Register();
What this line does is: it will call the Register method and register the module into NeatTools system. So later on, NeatTools could duplicate or recreate object instance by using this registered copy. If you fail to define this line, your module will become invisible to NeatTools system.
Programmer also need to override the className() and clone() methods. In NeatTools, I use the character string return by className() method to identify different objects. Please make sure not to define different class with the same name return by className(). The clone method will new and return a object instance. If you fail to define these methods, NeatTools could not generate the module you designed.
The constructor is an option. But usually you will initialize your data member or set the default input or output port number. 'igm' and 'ogm' are the variable represent the current input and output port number. In this example, I set 'igm' to 1 and the default value of 'ogm' (defined in JModuleObj) is 1 also. So here, this module has only one input and one output port. If you try to change the number of input or output port respond to property or input event, there are some complex issues on layout refresh problem. Please reference the source code in NeatTools Module develop kit and find out how to implement this feature.
NeatTools need more information on each input and output port. For example the data type, the attached edge, the tag, etc. The following methods will need to be override: (If you have some module which has common behavior, you can use one of the class as base class and use it to derive other class. This way, we could save time and space.)
NeatTools will these methods to display the tag or description for a particular input or output port. The default behavior in Module is following:
JString JModuleObj::inputTag(int n) {
char* tag[] = { "input", "enable(logical)"};
return tag[n];
}
JString JModuleObj::outputTag(int n)
{ return "output";}
So when user move to the port area, NeatTools system will display the tag by using the return value of this method.
Each input or output port could associate with different data type. Here we can return different data type identify for each different port. Or just return one data type identify for every port. The default behavior is following:
int JModuleObj::inputType(int n) { return JIntegerData::id;}
int JModuleObj::outputType(int n) { return JIntegerData::id;}
Here, it define every input and output port are all integer type. If you want to use other data type, please see the header files in NEAT directory. If you want to set different data type for each different port, you can write something like this:
int JTestObj::inputType(int n) {
switch (n) {
case 0: return JIntegerData::id;
case 1: return JStringData::id;
case 2: return JWaveData::id;
}
return JIntegerData::id;
}
This two methods define the accessibility of a input or output port. When it return true, NeatTools could add new connection to it. When it return false, NeatTools will indicate this port already been occupied. The default behavior is following:
boolean JModuleObj::inputAllowed(int n) { return false;}
boolean JModuleObj::outputAllowed(int n) { return false;}
So if you derive your module directly from JModuleObj, you will have to override these methods to ensure your input or output port could accept new connections. If you want input port accept only one connection, you can do something like this:
boolean JSquareObj::inputAllowed(int n)
{ return !inputSet(n).last();}
The inputSet(n) will return the link list of the input port number n. So if link is empty, its last() method will return null. So inputAllowed() will return true and NeatTools could accept new connection for this port. Otherwise, NeatTools will not accept new connection. Programmer could apply the outputSet(n) to the outputAllowed() method.
These two method decide the attach face that a connection would connect to. For inputFace(n), you could return either LEFT or TOP. For outputFace(n), you could return either RIGHT or BOTTOM. The default behavior is following:
int JModuleObj::inputFace(int n) { return (!n) ? LEFT : TOP;}
int JModuleObj::outputFace(int n) { return RIGHT;}
It means inputFace(0) will return LEFT and inputFace(1) will return TOP. and outputFace() always return RIGHT. So connection to the first input port will attach on left edge, but the second input port will attach on top edge.
These two methods decide the area that a port will accept connections. When user's mouse move within the area defined by JFRect (A floating point rectangle with x, y, with, height data member), NeatTools will show the inverse rectangle to indicate the port area. Module itself is derived from JFRect also. So itself has the x, y, with, and height data member which define the current position and dimension of the module. By using module's with and height value you can define inputArea or outputArea like this:
JFRect JModuleObj::inputArea(int n) {
if (!n) return JFRect(0, height/4, width/6, height/2);
return JFRect(width/4, 0, width/2, height/6);
}
JFRect JModuleObj::outputArea(int n)
{ return JFRect(width*5/6, height/4, width/6, height/2);}
But, I found out, it is too much trouble for most module with several input port and some of the module need to change the number of input or output port dynamically. So I wrote some utility method which will calculate the rectangle automatically. The default behavior is following:
JFRect JModuleObj::inputArea(int n) {
if (!n) return leftArea(n, 0, 1);
return topArea(n, 1, 1);
}
JFRect JModuleObj::outputArea(int n)
{ return rightArea(n, 0, 1);}
The leftArea, topArea, rightArea, and bottomArea method are defined in JMoudleObj.
JFRect topArea(int n, int start, int N,
double from = 0.25, double delta = 0.5, int factor = 6);
JFRect bottomArea(int n, int start, int N,
double from = 0.25, double delta = 0.5, int factor = 6);
JFRect leftArea(int n, int start, int N,
double from = 0.25, double delta = 0.5, int factor = 6);
JFRect rightArea(int n, int start, int N,
double from = 0.25, double delta = 0.5, int factor = 6);
The 'n' stand for the port number. 'start' means start from which port number. 'N' means for how many port. 'from' stand for the relative position that area start. 'delta' stand for the relative distance that 'N' port will occupy. 'factor' stand for the divide factor of area. If 'factor' is 6, it means area will have height/6 or width/6 dimension. So leftArea(n, 0, 3) means start from port 0 to port 2 (total 3 ports) will occupy area JFRect(0, height/4, width/6, height/2) and divide it into 3 portions from top to down are port0, port1, and port2.
These two method is pretty much like the inputArea and outputArea. But the only different is it will return the final attachment point of the connection to a particular port. You will see the link become one of the parameter. It is because, for those port could accept more than one connection, each connection will going to have different attachment point event they are belong to the same port. But using this parameter, we could decide its order and calculate the attachment point when necessary. Again, I wrote the following utility methods. The usage is exactly the same to area utility methods. Only you have to put in the extra link parameter.
JFPoint topPoint(int n, class JLinkObj& link, int start, int N,
double from = 0.25, double delta = 0.5);
JFPoint bottomPoint(int n, class JLinkObj& link, int start, int N, double from = 0.25, double delta = 0.5);
JFPoint leftPoint(int n, class JLinkObj& link, int start, int N, double from = 0.25, double delta = 0.5);
JFPoint rightPoint(int n, class JLinkObj& link, int start, int N, double from = 0.25, double delta = 0.5);
Display is a very important issue in NeatTools. I have been change the display mechanism several time to increase to through put especially for high frequency events that involve repaint modules. But there are only a few method that related to display. That's talk about paint, update, and repaint method:
void paint(JGraphics g, double dx, double dy, JRegion& rgn, double scale);
void update(JGraphics g, double dx, double dy, JRegion& rgn, double scale);
void repaint();
NeatTools will call paint method where there is a need to refresh the graphics contents of module. For example, when user do resize, scroll, scale, etc. operations on the NeatTools windows could cause a module's paint method get invoked. If module itself decide refresh itself to respond to its internal state's change (like LED receive a true event and decide to turn itself on), it could call the repaint() method. Eventually, NeatTools could invoke module's update method. (Depend on the situation, cause module could covered by other module or out of desktop's scope.) Usually, when receive paint, module will draw everything include frame and contents. But when received update, module could only draw the contents. To save space, usually, in paint method we will only draw frame and call the update to draw the contents. But basically, programmer could whatever he want depend on the situations. The following is an example on LED object:
void JLEDObj::paint(JGraphics g, double dx, double dy, JRegion& rgn, double scale) {
JRect rect = getIExtent(dx, dy, scale);
g.setJColor(moduleColor);
if ((rect.width > depth2) && (rect.height > depth2))
g.draw3DJRect(rect, depth);
update(g, dx, dy, rgn, scale);
}
void JLEDObj::update(JGraphics g, double dx, double dy, JRegion& rgn, double scale) {
JRect rect = getIExtent(dx, dy, scale);
if (value == 0) g.setJColor(bkgnd);
else g.setJColor(color);
if ((rect.width > depth2) && (rect.height > depth2)) {
g.fillJRect(rect.shrink(depth, depth));
} else g.fillJRect(rect);
}
The JGraphics object is the graphics context that module could make their graphics operations or setup parameters. It works like a media between program and actual devices. In this case, the JGraphics is always an area on screen, if user make some operation by calling JGraphics' methods, it will reflect the change to screen.
Here, in paint, first we use getIExtent to get the current module extent in integer screen unit. Cause NeatTools could display module in any scale. So, module will not know its current size on screen until its paint or update method get invoked. After this statement, the rect will store the current module size in pixel unit. Then, depend on the value itself, if value is false, we set the current color to background color, otherwise we set it to foreground color. If current size is large enough to draw the frame, we call g.draw3DJRect to draw the 3d frame. Then we call update to draw the contents.
In update, we follow the same process and later on fill the LED module with the proper color by using g.fillJRect methods.
void JLEDObj::engine(int n, JLinkObj& link) {
if (!n) {
int iv;
link.access(JIntegerData(iv));
setValue(iv);
} else processColor(n, link);
}
boolean JLEDObj::setValue(int _value) {
if (_value != value) {
value = _value;
broadcast(0);
repaint();
return true;
}
return false;
}
So, when will LED decide to update itself and make visual feedback to user ? Let's look at the engine method. If n is equal to zero (the input port on the left edge, in this case), it will use link.access to assign the integer value into iv variable. And call setValue(iv). In setValue method, we will check if the value need change, if it does, we update the value first and call broadcast(0) and repaint() to refresh its display. Later on, NeatTools will invoke it's update method to fill the color when necessary.
One important thing that NeatTools system does is provide user the capacity to layout modules and make connections between modules. But the other task that NeatTools does is equally important - module persistency. That means, NeatTools provide a way to let module store its current state and connections into secondary storage space like hard disk. And later on, retrieve the information and reconstruct every module, restore their state and rebuild their connections. So, how NeatTools do that ? NeatTools rely on two methods in module to accomplish this requirement.
protected:
virtual void writeContent(class JOutputStream& os);
virtual void readContent(class JDictionary& dict);
The implementation in LED looks like this:
void JLEDObj::writeContent(JOutputStream& os) {
JModuleObj::writeContent(os);
putObject(os, "color", color);
putObject(os, "bkgnd", bkgnd);
putInteger(os, "value", value);
}
void JLEDObj::readContent(JDictionary& dict) {
JModuleObj::readContent(dict);
JObject *obj = getObject(dict, "color");
if (obj) color = *(JColor*)obj;
obj = getObject(dict, "bkgnd");
if (obj) bkgnd = *(JColor*)obj;
value = getInteger(dict, "value");
}
'writeContent' method will be invoked when NeatTools want a module to write its current states into output stream. Programmer has to call base class's writeConnect method first. Cause every module will only handle the data member that declare in its object scope. Some times a data member is just for temporary usage, we could decide not to write their current state. readContent is the opposite to writeContent. When we try to 'put' a variable, we assign a string name to identify the variable. Later on, the readContent provide user a dictionary object which contain all the available variables. Programmer could use string name as a key to retrive the variables. All the putX and getX method are defined in JObject class. The only tricky thing is that, getObject could return null. In that case, we could check for that situation and assign object only when the return object is not null.
Bibliography
VITA
NAME OF AUTHOR: Yuh-Jye Chang
PLACE OF BIRTH: Wen-Lin, Taiwan
DATE OF BIRTH: Feb 22, 1966
GRADUATE AND UNDERGRADUATE SCHOOLS ATTENDED:
Stevens Institute of Technology, Hoboken, New Jersey
National Taiwan University, Taipei, Taiwan
DEGREES AWARDED:
Master of Computer Science, 1991, Stevens Institute of Technology
Bachelor of Mechanical Engineering, 1988, National Taiwan University
AWARDS AND HONORS:
Creative Entertainment Choice, 1997
Java Cup International Winner, 1996
National Taiwan University Symphony Vice-leader, 1987
PROFESSIONAL EXPERIENCE:
Research Assistant, Northeast Parallel Architectures Center, Syracuse University, 1997
Teaching Assistant, Department of Computer Information Science, Syracuse University, 1996
Project Leader, NewTek Corp, 1992
Robot Lab Assistant, Department of Mechanical Engineering, National Taiwan University, 1987
I.