Scott Hissam
James Ivers
Daniel Plakosh
Kurt C. Wallnau
April 2005
CMU/SEI-2005-TN-001
Predictable Assembly from Certifiable Components Initiative
Unlimited distribution subject to the copyright.
1 Introduction
A component technology comprises a component model and a runtime environment [Bachmann 00]. The component model defines the logical and implementation structure of components and applications constructed from components, and defines rules for how components may interact with one another and how they share resources. The runtime environment enforces these rules of interaction and provides basic services for resource sharing, communication, scheduling, and the like.
The Pin component technology is based on an earlier component technology developed by the Carnegie Mellon1 Software Engineering Institute (SEI) for the Environmental Protection Agency (EPA) [Plakosh 99]. Pin has since been further developed for use in prediction-enabled component technologies (PECTs) [Wallnau 03b]. Pin is a basic, simple component technology. A component technology for the class of systems we are targeting-embedded time- and safety-critical systems-should be small with an implementation that is (relatively) transparent; in fact, a large and opaque component technology would be counterproductive for this class of applications. There have been several generations of Pin implementations, and we expect more generations to follow.
About This Report
The objective of this report is to describe the logical structure of the Pin component technology and to document the application programming interface (API) for a version of Pin used in PECTs for substation automation [Hissam 03] and industrial robotics [Hissam 04a]. This report does not intend to propose a standard interface to Pin or any other component technology. In particular, we expect this API to undergo changes, some of which are already in development.
The intended audience for this report is the practitioner who is interested in understanding or developing software component technologies for embedded applications. Although this report does not give specific guidance on how to develop such a component technology, it does document a component technology that has been useful in nontrivial settings. Further insight into the design of Pin is provided in reports on the construction and composition language (CCL) [Ivers 02], [Wallnau 03a]; CCL is an architecture description language in the "component and connector" style that has been further specialized to work with the Pin component technology.
The logical structure of Pin is described in Section 2. Our current work on Pin is described in Section 3. Appendix A describes the Pin application programming interface (API), while Appendix B provides a simple but illustrative example Pin application.
2 Overview of Pin
2.1 Major Design Objectives
The design of Pin is governed by five overall design objectives that transcend requirements imposed by particular applications and that will continue to govern the evolution of Pin. In brief, Pin should
- have a simple programming model and an execution model that supports the semantics of UML statecharts
- provide various ways to enforce extrinsic (to Pin) design and implementation constraints
- introduce only the most basic features needed for building predictable embedded software
- be adaptable to the needs of new applications and platforms
- be freely distributable
The first objective is important for reasons of usability but is even more important for the purpose of automation. In particular, a simple programming model makes automated code generation straightforward and makes the code generators themselves relatively immune from changes to the Pin implementation. Further, specifications of component behavior, and the formal basis for their analyses, can build on a widely available specification language, UML. The second objective provides the flexibility needed to integrate new reasoning frameworks [Bass 05] into Pin-based PECTs; new reasoning frameworks may have assumptions that we wish to preserve as invariants in systems built using Pin. The third objective appeals to the benefits of parsimony: the simpler the implementation, the less chance it will introduce unanticipated runtime effects. The fourth objective recognizes that the needs of a broader range of applications and platforms can be supported without compromising a simple programming model by identifying key variation points, such as interaction mechanisms and scheduling policies. The fifth objective reflects our ultimate desire to make the results of our work widely available to practitioners, students, and researchers.
2.2 Overall Structure
Pin implements features of component technology that are frequently encountered in research prototypes as well as commercial products:
- Pin implements the container idiom for software components. Containers provide prefabricated "shells" in which custom code executes. All interactions between the custom code and its external environment are mediated by the container, which may impose container-type-specific coordination policies. A component is a container and its custom code.
- Pin components are fully encapsulated. The container ensures that custom code can interact with its environment only through container-mediated interfaces. While full encapsulation "feels" restrictive to developers accustomed to unfettered access to the runtime environment, the results are systems with fewer hidden component dependencies and fewer changes for unanticipated component interactions.
- Components are independently deployable binary implementations with explicit context dependencies (a widely accepted starting point, popularized by Szyperski [Szyperski 02]). Each Pin component is implemented as a distributable dynamic link library (DLL). Since components are fully encapsulated, all environmental dependencies (on the runtime environment or other components) are fully explicit.
- Pin supports a model of pure assembly. Applications are constructed by connecting components using a repertoire of connectors. Each connector may impose coordination policies beyond those provided by containers; for example, queuing policies on message buffers. Assembly is "pure" because it is declarative; point-to-point custom interaction code (a.k.a. "glue" code) is not permitted.2
- A component runtime environment provides services and enforces component interaction policies. Services include access to the underlying platform; for example, timers, interrupts, and input devices. Interaction policies governing shared resources, such as process scheduling and intercomponent communication, are also provided by the runtime. Lastly, the runtime provides a portability layer for components and their assemblies.
The overall logical structure of Pin is depicted in Figure 1.
Figure 1: Major Structure of the Pin Component Technology
Pin V1.0 has a number of limitations. Some are "principled restrictions" that reflect our underlying design philosophy, as well as the special considerations of our intended application domain (embedded, safety- and performance-critical software). Other limitations arise only from expediency and will likely be relaxed in future implementations. It is not always clear whether a limitation is a principled restriction or an expediency, and the interplay of design objectives 3 and 4 almost requires a flexible boundary between those two things.
Without prejudice to classification, the following summarizes the main limitations of Pin V1.0:
- Assembly topologies are fixed: we assume a closed world with static configurations.
- Distributed and hierarchical assembly (i.e., assemblies of assemblies) is not supported.
- Each component reaction (see Section 2.3) has a thread of control; the notion of unthreaded reactions (as outlined by Ivers, Sinha, and Wallnau [Ivers 02]) is not supported.
- Message sizes for intercomponent communication are fixed, and queue lengths for connectors are fixed (but statically configurable).
- Only two types of connectors are supported-for synchronous and asynchronous interaction (although different connector implementations can be statically configured).
- Only one type of container is provided (although more are currently under development for the next version of Pin).
2.3 Components
A Pin component consists of two parts: (1) a user-supplied (custom) function and (2) the Pin-supplied (prefabricated) container function. The interface structure of a Pin component is displayed in Figure 2.
User-supplied code must conform to an interface contract defined by the container ("user code API" in Figure 2); the container uses this interface to invoke (via the "user code plug-in") user-supplied code in response to requests from the Pin runtime environment or from other components. Conversely, the container provides an interface ("container API") that custom code uses to requests service from the runtime environment or from other components. The container also presents a single interface to the environment ("component API"), which conforms to an environment-defined plug-in interface (not depicted). The container provides two additional plug-in interfaces ("directory server plug-in" and "IPC plug-in")3 to make it possible to deploy components to different runtime environments, possibly having different intercomponent (or interprocess) communication mechanisms. Pin components are packaged and deployed as dynamic link libraries (DLLs).
Figure 2: Pin Component and Container Contracts
The user code API and container API are quite simple, each defining fewer than ten operations. The user code API defines operations for creating, destroying, and initializing runtime instances of the component. The container API provides operations for sending requests for service to the environment. The simplicity of these interfaces reflects our concern to make the programming model for Pin as simple as possible.
In practice, the isolation of the custom code from its environment is not as complete as depicted in Figure 2; there are inevitable dependencies on standard runtime libraries. These dependencies could be problematic if external libraries violate reasoning framework assumptions. For example, an external library might introduce a source of unbounded priority inversion, which in turn would invalidate the predictions of a performance theory. There are a variety of ways to enforce strict isolation. (This is a topic of ongoing SEI research.)
The logical structure of a Pin component (in particular, the custom code part of a Pin component) is depicted in Figure 3. Wallnau and Ivers provide a more detailed description of the concepts [Wallnau 03a].
Figure 3: The Logical Structure of a Pin Component: Pins and Reactions
The custom code of a Pin component is organized as a set of one or more reactions. The container creates a thread for each reaction.4 This thread waits for the arrival of stimulus on a sink pin; stimulus is FIFO queued. On receipt of stimulus, user code is executed; when this processing is complete, control is returned to the container, which then checks for further stimulus, ad infinitum.
Each reaction accepts stimuli from one or more sink pins and produces responses on zero or more source pins. Each sink pin provides stimulus to at most one reaction; each source pin is used by at least one reaction. Pins support synchronous and asynchronous interaction. Synchronous interaction has the familiar procedure-call semantics (although it is implemented using a messaging system), while asynchronous interaction has the familiar event-based semantics.
2.4 Assemblies
Component instances receive stimulus through sink pins and respond through source pins; enabling interaction among component instances requires that we connect a source pin of one component instance to the sink pin of another. An assembly of components consists of a static topological arrangement of component instances.
Pin V1.0 does not explicitly support the notion of assembly. In particular, there is no notion of assembly container (although this will change in a future release). Instead, we construct assemblies implicitly as a main (top-level) executable program that manages the component and (implicit) assembly life cycle. Typically, assembly programs (also called assembly "controllers" in the Pin vernacular) are generated automatically from CCL specifications. The life cycle of an assembly controller is shown in Figure 4.

Figure 4: The Assembly Controller Life Cycle
There is no intrinsic reason why component instances in different controllers can't be connected (indeed, we use a directory server to look up component interface details, and the connector mechanisms supported by the Pin runtime are UDP based). However, we will not consider Pin as supporting distributed assembly (or uniprocessor hierarchical assembly) until such concepts are explicitly supported via assembly containers or their equivalents.
2.5 Runtime Environment
As discussed in earlier reports (e.g., in the work of Bachmann and colleagues [Bachmann 00]), a component runtime environment plays a role with regard to component assemblies that is analogous to the role operating systems play with regard to processes. The analogy is a strong one, and, not surprisingly, the boundary between component runtime and operating system is fuzzy and, to some extent, arbitrary.
The component runtime for Pin V1.0 is a pragmatic amalgamation of services needed to support prototypes built for electric grid substation automation [Hissam 03] and industrial robot control [Hissam 04a]. Only the major elements of the Pin V1.0 runtime are shown in Figure 5.
Figure 5: Pin V1.0 Runtime Environment
There are two layers of service in the runtime. The bottom layer provides real-time thread support and is implemented by a commercial product that provides these services as extensions of the Microsoft Windows NT operating system.5 On top of this bottom layer is (1) a directory service that is used by the assembly controller to connect components and (2) a variety of other services used by components and assembly controllers.
This report does not document the programming interfaces to the Pin V1.0 runtime environment; as discussed in the next section, that part of the Pin component technology is being extensively reworked.
3 Current Work
The version of Pin described in this report has a significant dependency on a commercial software6 that supports the development of real-time applications on Microsoft Windows NT. While this product was adequate for our immediate purpose and consistent with the assumptions of the
ABA performance theory [Hissam 03], we could not develop performance reasoning frameworks that exploit alternative scheduling disciplines, such as earliest deadline first (EDF). Beyond this restriction, the dependency on a commercial product limits our options for distributing Pin to clients or as an open source product.
For these (and other) reasons, we are currently rehosting Pin to our own virtual operating systems layer, called the Pin Kernel Services. This layer is currently implemented on Windows NT and Windows CE, but it can, in principle, be rehosted to any Unix variant7 as well as to "bare" hardware. The major elements of the Pin kernel are shown in Figure 6.
Figure 6: Pin Runtime Environment and the Pin Kernel
Revisions are being made to the Pin component model that will influence the structure of the Pin Component Model Services, shown in undifferentiated form in Figure 6. The two most significant areas of revision are in the treatment of event semantics and the support for distributed assemblies.
Pin event semantics are being revised to more directly reflect UML statechart semantics. In particular, a range of UML event classes will be supported by Pin, including (in addition to "pin" events) UML change and time events. It is important to note that the UML standard deliberately leaves semantic aspects of statecharts undefined, allowing some implementation latitude for UML tool vendors. We have selected a consistent semantics for statecharts within the space of allowed variation.
Pin V1.0 does not support distributed assemblies. Although we could (and did) handcraft solutions to permit components in one assembly, executing on one CPU, to communicate with components in another assembly on another CPU, these solutions were ad hoc and not reflected in the semantics of CCL. We are currently investigating several alternative approaches and will report on our progress in a future technical note.
4 Summary
Pin is a basic, simple component technology suitable for building embedded software applications. Pin implements the container idiom for software components. Containers provide a prefabricated "shell" in which custom code executes and through which all interactions between custom code and its external environment are mediated. Pin is a component technology for pure assembly (systems are assembled by selecting components and connecting their interfaces, which are composed of communication channels called pins) and has been used as a foundation for our work on PECTs.
This report describes the main concepts of Pin and documents the C-language interface to Pin V1.0. It also provides insight into some of the changes we are making currently to improve Pin. Table 1 summarizes those changes.
Table 1: Summary of Planned Improvements to Pin
Appendix A Pin's C API
A.1 Data Structures
The following are commonly used data types and structures supporting many of the component-supplied functions and Pin runtime support functions. Developers of assembly controllers will also refer to these functions.
IPC_MSG
Synopsis
#include <ComponentSpec.h>
#define IPC_MAXMSGSIZE 1536
typedef struct
{
IPC_HEADER header;
char data[IPC_MAXMSGSIZE - sizeof (IPC_HEADER)];
} IPC_MSG;
IPC_MSG is the structure used in all component interactions to send and receive messages, where
header
(reserved) used by the Pin runtime to dispatch messages. Elements within this portion of the structure should be considered opaque.
See Also
SendOutSourcePin(), SendOutSourcePinWait(), SendReply()
Example
IPC_MSG MessageOut; SPrintf(MessageOut.data,"Clock From %s Pin %d", Reaction->Instance->UniqueName,0); SendOutSourcePin (Reaction, 0, &MessageOut, (short)(Rt_strlen(MessageOut.data)+1), IPC_WAITFOREVER);
TCommonAnswer
#include <ComponentSpec.h>
typedef struct
{
IPC_MSG *MessageReply;
} TCommonAnswer;
TCommonAnswer is the structure used to exchange data with the callback associated with a synchronous reply on a synchronous pin, as with SendOutSourcePinWait(). The callback can obtain the reply from within this data structure, where
message reply from the synchronous pin interaction
See Also
IPC_MSG, SendOutSourcePinWait(), SendReply(), TCommonHandler()
Example
TCommonAnswer *answer=(TCommonAnswer*)Data;
RtPrintf("Instance %s Pin %d Received %s\n",
Reaction->Instance->UniqueName, 2,
answer->MessageReply->data);
TCommonMsg
Synopsis
#include <ComponentSpec.h>
typedef struct
{
IPC_MSG *MessageIn;
short BytesIn;
short src_id;
short cmd;
short msg_type;
short user_def;
} TCommonMsg;
TCommonMsg is the structure used to exchange data with common handlers when passing PINMSG (for instance, a reaction handler which is of type TCommonHandler() and TReason is PINMSG), where
message being set for a given pin interaction
BytesIn
size in bytes of the data portion of MessageIn
source pin from which the message was sent.
cmd
sink pin upon which the message was received
user-defined field
IPC_MSG, TCommonHandler(), SendOutSourcePin(), SendOutSourcePinWait().
Example
BOOL Reaction_1_Handler
(TReactions *Reaction, TReason Reason, void * Data)
{
...
if (Reason==PINMSG)
{
TCommonMsg *msg=(TCommonMsg *)Data;
RtPrintf("R1 %s Pin %d Received Message: %s\n",
Reaction->Instance->UniqueName,
msg->cmd, msg->MessageIn->data);
}
}
TCommonTimeOut
#include <ComponentSpec.h>
typedef struct
{
long LastTimeout;
long NextTimeout;
} TCommonTimeOut;
TCommonTimeOut is the structure used to exchange timeout information with common handlers when passing TIMEOUT (for instance, a reaction handler which is of type TCommonHandler() and TReason is TIMEOUT), where
LastTimeout
last timeout value (in milliseconds) that expired, thereby causing the invocation of the reaction handler
NextTimeout
new timeout value (in milliseconds) to use upon return from the reaction for the next timeout. Setting NextTimeout to zero (0) will disable all future timeouts.
TCommonHandler()
Example
BOOL Reaction_1_Handler
(TReactions *Reaction, TReason Reason, void * Data)
{
...
if (Reason==TIMEOUT)
{
TCommonTimeOut *to=(TCommonTimeOut *)Data;
RtPrintf ("Reaction timeout at %ld\n", to->LastTimeout);
to->NextTimeout = to->LastTimeout + 100; // new next timeout
}
}
TCommonTmrEvent
#include <ComponentSpec.h>
typedef struct
{
REACTION_TIMER_HANDLE ReationTimerHandle;
DWORD dwUser;
DWORD NextDelay;
} TCommonTmrEvent;
TCommonTmrEvent is the structure used to exchange timer information with common handlers when passing TMR (for instance, a reaction handler which is of type TCommonHandler() and TReason is TMR), where
ReactionTimerHandle
the system handle to the common handler just invoked. This handle is useful in destroying the handler associated with a timer.
new timer value (in milliseconds) to use upon return from the reaction for the next timer. Setting NextDelay to zero (0) will cause the timer to expire immediately and TCommonHandler() to be invoked. Setting NextDelay to INFINITE will prevent the timer from expiring under any conditions.
TCommonHandler(), CreateReactionTimer()
Example
BOOL Reaction_1_Handler
(TReactions *Reaction, TReason Reason, void * Data)
{
...
if (Reason==TMR)
{
TCommonTmrEvent *tmrevt=(TCommonTmrEvent *)Data;
Time+=500;
RtPrintf("ReactionHandler Instance %s Reaction %d\n",
Reaction->Instance->UniqueName, tmrevt->dwUser);
tmrevt->NextDelay=Time
}
}
TComponentInfo
#include <ComponentSpec.h>
typedef struct
{
char *Name;
unsigned int NumSourcePins;
unsigned int NumSinkPins;
unsigned int NumReactions;
} TComponentInfo;
TComponentInfo consists of general, structural information about a component to include its name, number of source pins, and number of sink pins, and the total number of reactions it supports, where
character string constant that is null terminated and identifies the name of the component
NumSourcePins
non-negative integer value indicating the total number of source pins
non-negative integer value indicating the total number of sink pins
NumReactions
non-negative integer value indicating the total number of reactions
Example
TComponentInfo ComponentInfo={
"DISTCLOCK105",
NUM_SOURCE_PINS,
NUM_SINK_PINS,
NUM_REACTIONS,
};
GetNumSourcePins(), GetNumSinkPins(), GetNumReactions(), GetSourcePinInfo(), GetSinkPinInfo(), GetReactionInfo()
TComponentInstance
Synopsis
#include <ComponentSpec.h>
typedef struct _TComponentInstance
{
struct _TPinComponent *Component;
char *UniqueName;
TSourcePins *SourcePins;
TReactions *Reactions;
void *InstanceData;
struct _TReactionTimer
*TimerHandlesIndexToPtr[MAX_REACTION_TIMER_HANDLES];
int
TimerHandlesFreeListNext[MAX_REACTION_TIMER_HANDLES];
int TimerHandlesFreeList;
CRITICAL_SECTION TimerHandlesCriticalSection;
} TComponentInstance;
TComponentInstance consists of general, structural information about an instance of a component to include the instance's name and data specific to a single instance, where
handle to TPinComponent
Name
character string constant that is null terminated and identifies the unique name of the component instance
SourcePins
handle to the list of source pins
Reactions
handle to the list of source pins
InstanceData
handle to the list of source pins
TimerHandlesIndexToPtr
reserved
TimerHandlesFreeListNext
reserved
TimerHandlesFreeList
reserved
TimerHandlesCriticalSection
reserved
ConfigureInstance(), DeleteInstance(), CreateInstance(), SourceAddSinkPin(), StartInstance(), StopInstance(), LoadComponent()
Example
TComponentInstance *InstanceSimpleClock1;
if ((InstanceSimpleClock1=CreateInstance
(PinSimpleClock, "clock1",
&SimpleClockComponentProperties[0],
sizeof(COMPONENT_SimpleClock_ARGS)))!=NULL)
{
RtPrintf("Instance clock1 Created\n");
}
else
RtPrintf("Failed to Create Instance clock1\n");
TPinComponent
Synopsis
#include <ComponentSpec.h>
typedef struct _TPinComponent
{
HINSTANCE hLibModule;
T_ABB_IPC_Functions ABB_IPC_Functions;
TPinDirServ PinDirServ;
TContoller Controller;
T_GetNumSinkPins _GetNumSinkPins;
T_GetNumSourcePins _GetNumSourcePins;
T_GetNumReactions _GetNumReactions;
T_GetReactionInfo _GetReactionInfo;
T_GetSourcePinInfo _GetSourcePinInfo;
T_GetSinkPinInfo _GetSinkPinInfo;
T_CreateInstance _CreateInstance;
T_DeleteInstance _DeleteInstance;
T_SourceAddSinkPin _SourceAddSinkPin;
T_SetReactionPriority _SetReactionPriority;
T_ConfigureInstance _ConfigureInstance;
T_SetReactionQueueLength _SetReactionQueueLength;
T_SetReactionTimeOut _SetReactionTimeOut;
T_StartInstance _StartInstance;
T_StopInstance _StopInstance;
T_SetMeasureExecutionTime _SetMeasureExecutionTime;
} TPinComponent;
TPinComponent is used as a system utility structure whose structure elements are all reserved.
TComponentInstance, ConfigureInstance(), DeleteInstance(), CreateInstance(), SourceAddSinkPin(), StartInstance(), StopInstance(), LoadComponent()
Example
TPinComponent *PinSimpleClock;
if ((PinSimpleClock=LoadComponent("SimpleClock.dll"))==NULL)
{
RtPrintf("Failed to Load SimpleClock\n");
ExitProcess(0);
}
else
RtPrintf("SimpleClock Load Successful\n");
TPinInfoSink
Synopsis
#include <ComponentSpec.h>
typedef struct{
char *PinName;
char *PinType;
} TPinInfoSink;
TPinInfoSink holds user-defined values for the name of the sink pin and the name of its type, where
The semantic significance of the values is user defined.
SourceAddSinkPin()
Example
TPinInfoSink SinkPins[NUM_SINK_PINS]=
{
{"Sporadic Server Request", "SS.request" }
};
TPinInfoSource
Synopsis
#include <ComponentSpec.h>
typedef struct
{
char *PinName;
char *PinType;
} TPinInfoSource;
TPinInfoSource holds user-defined values for the name of the source pin and the name of its type, where
PinName
character string constant that is null terminated and identifies the name of the source pin
PinType
character string constant that is null terminated and identifies the type of the source pin
The semantic significance of the values is user defined.
SourceAddSinkPin()
Example
TPinInfoSource SourcePins[NUM_SOURCE_PINS]=
{
{"Source Pin 0 (r0)", "TEST"},
{"Source Pin 1 (r1)", "TEST"},
};
TReactions
Synopsis
#include <ComponentSpec.h>
typedef struct _TReactions
{
unsigned int ReactionIndex;
struct _TComponentInstance *Instance;
short QueueSize;
int Priority;
TThreadInfo ThreadInfo;
short IPC_SlotID;
BOOL Valid;
long TimeOut;
BOOL MeasureExecutionTime;
} TReactions;
The TReactions structure holds runtime information about an individual reaction and is passed as an argument to TCommonHandler(), where
ReactionIndex
non-negative integer representing the index of the reaction in the TReactionsInfo
structure
Instance
character string constant that is null terminated and identifies the name of the reaction's component instance
QueueSize
non-negative integer of the queue size for holding messages for the reaction
Priority
non-negative integer denoting the reaction's priority
ThreadInfo
reserved
IPC_SlotID
reserved
Valid
reserved
TimeOut
non-negative integer indicating the timeout for the reaction that will generate a TIMEOUT message should no other message type arrive
MeasureExecutionTime
Boolean indicating whether (TRUE) or not (FALSE) measurement events should be generated by the reaction
TCommonHandler(), TReactionInfo
Example
BOOL Reaction_1_Handler
(TReactions *Reaction, TReason Reason, void * Data)
{
...
if (Reason==PINMSG)
{
TCommonMsg *msg=(TCommonMsg *)Data;
RtPrintf("R1 %s Pin %d Received Message: %s\n",
Reaction->Instance->UniqueName,
msg->cmd, msg->MessageIn->data);
}
}
TReactionsInfo
Synopsis
#include <ComponentSpec.h>
typedef struct
{
unsigned int NumSourcePins;
unsigned int NumberOfSinkPins;
unsigned int *SourcePins;
unsigned int *SinkPins;
short DefaultQueueSize;
int DefaultPriority;
long DefaultTimeOut;
BOOL DefaultMeasureExecutionTime;
TCommonHandler Handler;
TCommonHandler TimeoutHandler;
} TReactionsInfo;
The TReactionsInfo structure is initialized at compile time and accessed by the system to acquire information about the handlers in the system and the associated source and sink pins related to that handler, where
NumSourcePins
non-negative integer indicating the number of source pins associated with the handler
NumberOfSinkPins
non-negative integer indicating the number of sink pins associated with the handler
SourcePins
list of source pins (whose number matches NumSourcePins) associated with the handler
SinkPins
list of sink pins (whose number matches NumberOfSinkPins) associated with the handler
DefaultQueueSize
non-zero integer indicating the size of the input queue to the handler for inbound message interactions
DefaultPriority
non-negative integer for the default priority for the handler, used for scheduling
DefaultTimeOut
non-negative integer for the default timeout to use before invoking the handler after no messages have been received. A value of 0 disables timeouts.
DefaultMeasureExecutionTime
Boolean value of whether (TRUE) or not (FALSE) measurement traces should be emitted for pin interactions with this handler
Handler
pointer to the normal message handler
TimeoutHandler
pointer to the timeout handler (which can be the same as the normal handler)
GetReactionInfo()
Example
TReactionsInfo ReactionInfo[NUM_REACTIONS]=
{
{
REACTIONS_0_NUM_SINKS,
REACTIONS_0_NUM_SOURCE,
NULL,
Reactions_0_Source,
5,
10,
IPC_WAITFOREVER,
FALSE,
Reaction_0_TimeoutHandler
}
};
TReason
Synopsis
#include <ComponentSpec.h>
typedef enum
{
PINMSG,
TMR,
TIMEOUT,
ANSWER
} TReason;
TReason is used to differentiate between messages passed to TCommonHandler(), where
PINMSG
indicates a message conforming to
TCommonMsg
TMR
indicates a message conforming to
TCommonTmrEvent
TIMEOUT
indicates a message conforming to TCommonTimeOut
indicates a message conforming to TCommonAnswer
TCommonHandler(), SendReply(), CreateReactionTimer(), TReactionsInfo
Example
BOOL Reaction_0_Handler
(TReactions *Reaction, TReason Reason, void * Data)
{
if (Reason==PINMSG)
{
// Handle TCommonMsg
}
else if (Reason==TMR)
{
// Handle TCommonTmrEvent
}
else if (Reason==TIMEOUT)
{
// Handle TCommonTimeOut
}
else if (Reason==ANSWER)
{
// Handle TCommonAnswer
}
}
A.2 User Code API
Functions appearing in this section are functions that are required to be provided by the user-supplied portion of the component. The container will invoke these functions as per the Pin component life cycle.
CreateComponentInstance
Synopsis
#include <ComponentFuncs.h> BOOL CreateComponentInstance( void **Data, void *State, unsigned int SizeOfState );
CreateComponentInstance() is called when an instance of a component is to be created. It is the first instance-specific call made by the Pin runtime. This function should create all instance-specific data and state information relevant to an instance object. The data and state information created are intended to be private to this instance. Any specific initialization data and state information relevant to this component and instance are passed in the State pointer. If this data and state are to persist for the lifetime of the instance created, heap memory allocation should be performed in this function, and references to that memory created can be stored as callback in Data.
Component defined data in State is not guaranteed to persist after the call to
CreateComponentInstance() and must be saved prior to a return from this function.
Data
non-null pointer provided by the Pin runtime and used by an instance of a component to save instance-specific data and state information. The pointer set by
CreateComponentInstance() is saved in the TReaction data structure element
TComponentInstance.InstanceData.
State
If non-null, the value is a pointer provided by the controller to data and state information intended to be specific to the instance of a component that is being created. A NULL value indicates that no data or state information was passed.
If State is non-null, SizeOfState is a positive non-zero integer indicating the number of bytes in memory of State.
TRUE
indicates that CreateComponentInstance() was successfully able to create an instance of a component
FALSE
indicates that CreateComponentInstance() failed to successfully create an instance of a component
CreateInstance()
Example
BOOL CreateComponentInstance(
void **Data, void *State, unsigned int SizeOfState)
{
if (Data==NULL) return(FALSE);
else *Data=NULL;
if (State != NULL) {
*Data =
RtAllocateLockedMemory(SizeOfState);
if (*Data == NULL)
return (FALSE);
Rt_memcpy (
*Data, State, sizeof(SizeOfState));
}
return (TRUE);
}
DeleteComponentInstance
Synopsis
#include <ComponentFuncs.h> BOOL DeleteComponentInstance( void **Data );
DeleteComponentInstance() is called when an instance of a component is to be deleted, and there are no further references to a component instance to be made. This is the last instance-specific call made by the Pin runtime. This function should free all instance-specific data and state information relevant to an instance object from the heap.
TRUE
indicates that DeleteComponentInstance() was successfully able to destroy an instance of a component
FALSE
indicates that DeleteComponentInstance() failed to successfully destroy an instance of a component
DeleteInstance()
Example
BOOL DeleteComponentInstance(void **Data)
{
if (Data==NULL) return(FALSE);
else {
if (*Data) RtFreeLockedMemory (*Data);
*Data=NULL;
}
return(TRUE);
}
ReactionInitialize
Synopsis
#include <ComponentFuncs.h> void ReactionInitialize ( TReactions *Reaction, int ReactionIndex );
ReactionInitialize() is called after an instance of a component is created and before the component instance is to receive messages on sink pins. This function is called during the component instance's startup phase and is invoked by StartInstance(). Any reaction-specific actions that need to be completed before messages are received should be done here (e.g., creating timers).
Reaction
non-null pointer provided by the Pin runtime and used by an instance's reaction to access instance- and reaction-specific data and state information
ReactionIndex
non-negative integer value indicating the index of the reaction being initialized. This index is determined by the total number of reactions and the TReactionsInfo statically declared for the component.
None
StartInstance()
Example
void ReactionInitialize
(TReactions *Reaction,int ReactionIndex)
TUserData *Data;
Data=(TUserData *) Reaction->Instance->InstanceData;
if ((Data->Handle[ReactionIndex]=
CreateReactionTimer
(Reaction,ReactionTmrHandler,12,500,
TRUE,ReactionIndex))== NULL_INDEX )
{
RtPrintf("Initialize Reaction Error\n");
}
else
RtPrintf("Initialize Reaction OK\n");
}
ReactionTerminating
Synopsis
#include <ComponentFuncs.h> void ReactionTerminating ( TReactions *Reaction, int ReactionIndex );
ReactionTerminating() is called prior to terminating a component instance, indicating that reactions handling messages on the sink pin should cease. This function is called during the component instance's shutdown phase and is invoked by StopInstance(). Any reaction-specific actions that need to be completed before terminating the component instance should be done here (e.g., destroying timers).
Reaction
non-null pointer provided by the Pin runtime and used by an instance's reaction to access instance- and reaction-specific data and state information
ReactionIndex
non-negative integer value indicating the index of the reaction being terminated. This index is determined by the total number of reactions and the TReactionsInfo statically declared for the component.
None
StopInstance()
Example
void ReactionTerminating
(TReactions *Reaction,int ReactionIndex)
{
TUserData *Data;
Data=(TUserData *) Reaction->Instance->InstanceData;
if (DestroyReactionTimer
(Reaction,Data->Handle[ReactionIndex])==TRUE)
RtPrintf("Terminating Reaction OK\n");
else
RtPrintf("Terminating Reaction Failed\n");
}
TCommonHandler Synopsis
#include <ComponentSpec.h> typedef BOOL (*TCommonHandler) ( struct _TReactions *Reaction, TReason Reason, void * Data );
TCommonHandler() is a function prototype and not a specific function to be provided by the component developer. The Pin runtime will invoke specified handlers according to the data structures created by the component developer, such as TReactionsInfo.Handler and TReactionsInfo.TimeoutHandler, or provided as parameters to other functions (e.g., CreateReactionTimer()). Such handlers must conform to the type definition for this function prototype.
Each handler is called with three things: (1) a pointer to a structure containing information about the reaction, (2) the reason the handler was invoked, and (3) callback data and state information for the specific instance of the component to which this handler belongs.
Reaction
non-null pointer provided by the Pin runtime and used by an instance's reaction to access instance- and reaction-specific data and state information
Reason
reason why TCommonHandler() was called: PINMSG,TIMEOUT, TMR, or ANSWER
a non-null pointer provided by the Pin runtime and used to access instance-specific data and state information
TRUE
indicates to the Pin runtime that the handler encountered no reportable errors
FALSE
indicates to the Pin runtime that the handler encountered an exception
TReactionInfo, TReason, SendOutSourcePin(), SendOutSourcePinWait(), SendReply(), CreateReactionTimer()
Example
BOOL Reaction_1_Handler
(TReactions *Reaction, TReason Reason, void * Data)
{
if (Reason==PINMSG)
{
RtPrintf("R1 %s Pin %d Received Message: %s\n",
Reaction->Instance->UniqueName,
msg->cmd, msg->MessageIn->data);
}
else if (Reason==TMR)
{
RtPrintf("R1 Timer Expired.\n");
}
}
A.3 Container API
User-supplied component code is provided for the functions in this section to manage behavior and interactions with other components and the Pin runtime.
CreateReactionTimer
Synopsis
#include <ComponentSpec.h> REACTION_TIMER_HANDLE CreateReactionTimer ( TReactions *Reaction, TCommonHandler Callback, int Priority, DWORD Delay, BOOL Periodic, DWORD dwUser );
CreateReactionTimer() will create a timer having a specified delay and priority that will invoke a specific timer handler (i.e., callback). When a timer expires, a TMR message is placed on the reaction queue for the specified timer handler.
Reaction
non-null pointer indicating which instance's reaction the timer should be assigned to
Callback
non-null pointer indicating the TCommonHandler() handler to call when the timer expires
Priority
non-negative integer indicating the priority at which the timer is to operate. The range is 0 >= Priority <= 255.
Delay
non-negative integer indicating the timer's delay before expiring. A zero delay will cause the timer to expire immediately (while at its assigned priority).
Periodic
If TRUE, the timer will continue to expire at the given priority and rate (delay). If FALSE, the timer will expire only once.
dwUser
pointer to user-defined callback data. This pointer will be provided to the callback when the timer expires.
A failure will result in a return value of NULL_INDEX; otherwise the return value is a valid REACTION_TIMER_HANDLE.
A reaction can have at most MAX_REACTION_TIMER_HANDLES timer handles.
CreateReactionTimer() will fail with NULL_INDEX if more than MAX_REACTION_TIMER_HANDLES timer handlers are being created. Use
DestroyReactionTimer() to free up unused handles or handles that are no longer needed.
DestroyReactionTimer()
Example
void ReactionInitialize
(TReactions *Reaction,int ReactionIndex)
{
TUserData *Data;
Data=(TUserData *) Reaction->Instance->InstanceData;
if ((Data->Handle[ReactionIndex]=
CreateReactionTimer
(Reaction,ReactionTmrHandler,12,500,
TRUE,ReactionIndex))== NULL_INDEX )
{
RtPrintf("Initialize Reaction Error\n");
}
else
RtPrintf("Initialize Reaction OK\n");
}
DestroyReactionTimer
Synopsis
#include <ComponentSpec.h> BOOL DestroyReactionTimer( TReactions *Reaction, REACTION_TIMER_HANDLE Handle );
DestroyReactionTimer() will destroy or otherwise remove a timer created with
CreateReactionTimer(). The timer destroyed will no longer generate messages for the specified reaction.
Reaction
non-null pointer indicating from which instance's reaction the timer should be destroyed
Handle
handle to the specific timer to be destroyed. This handle was previously returned by CreateReactionTimer().
TRUE if the timer was destroyed successfully, FALSE otherwise.
Handle must have been returned by CreateReactionTimer() and is in the range of 0 < Handle <= MAX_REACTION_TIMER_HANDLES.
CreateReactionTimer()
Example
void ReactionTerminating
(TReactions *Reaction,int ReactionIndex)
{
TUserData *Data;
Data=(TUserData *) Reaction->Instance->InstanceData;
if (DestroyReactionTimer
(Reaction,Data->Handle[ReactionIndex])==TRUE)
RtPrintf("Terminating Reaction OK\n");
else
RtPrintf("Terminating Reaction Failed\n");
}
NotifyController
#include <ComponentSpec.h> int NotifyContoller ( TComponentInstance *Instance, int code, char *string );
NotifyController() is used by component instances to send the following to the controller of another instance: (1) a user-defined message or (2) code and an optional character string. This function is useful in communicating exception conditions to the controller, requiring controller attention (such as shutdown).
Instance
non-null pointer indicating which component instance is performing the notification
code
user-defined integer (optional) that is passed to the controller and is application dependent
user-defined string (optional) that is passed to the controller and is application dependent
non-null pointer indicating which component instance is performing the notification
CONTROLLER_NOT_FOUND
Either the shared memory segment for message passing has not been initialized (via StartPinInterface()) or the queue for delivering the message to the controller has been deleted.
INVALID_INSTANCE
An instance was passed as a null pointer.
INVALID_INSTANCE_UNIQUE_NAME
The instance name was either of zero length (an empty, but non-null string) or too long.
STRING_MESSAGE_TOO_LONG
The string was either of zero length (an empty, but non-null string) or too long.
The queue for delivering message to the controller is full.
CONTROLLER_UNKNOWN_ERROR
An error of the underlying IPC mechanism for delivering messages has occurred for an unknown reason.
Errors generated by this function and the conditions are described above under "Description."
WaitForNotifications()
Example
BOOL Reaction_1_Handler
(TReactions *Reaction, TReason Reason, void * Data)
{
static DWORD Time=0;
if (Reason==PINMSG)
{
if (NotifyContoller(Reaction->Instance,
543212345,"It works")==SUCCESS)
RtPrintf("Done Notification Sent\n");
else
RtPrintf("Notification Send Error\n");
}
}
SendOutSourcePin
#include <ComponentSpec.h> BOOL SendOutSourcePin ( TReactions *Reaction, unsigned int SourcePin, IPC_MSG *MessageOut, short MsgSize, long Timeout );
SendOutSourcePin() is used to send out an asynchronous message via a component instance's source (or stimulus) pin. SendOutSourcePin() will block long enough to queue the message on the one or more queues of the connected, and interoperating, sink (or receiving) pins.
Reaction
non-null pointer indicating the reaction generating the message
SourcePin
index of the source pin on which the message is being generated
MessageOut
message being sent
MsgSize
size in bytes of MessageOut
Timeout
the length of time in milliseconds to wait for delivering messages that would block (e.g., in the case of a full queue). A timeout of IPC_WAITFOREVER will cause SendOutSourcePin() to wait until the message can be delivered to the queue of the destination sink pin.
SendOutSourcePinWait() will fail if the component instance does not have any source pins or failed in the IPC code because of a timeout, message size error, invalid source pin ID, or unrecoverable system error.
SendOutSourcePinWait()
Example
BOOL Reaction_0_TimeoutHandler
(TReactions *Reaction, TReason Reason, void * Data)
{
if (Reason==TIMEOUT)
{
IPC_MSG MessageOut;
TCommonTimeOut *to=(TCommonTimeOut *) Data;
SPrintf(MessageOut.data,"Clock From %s Pin %d",
Reaction->Instance->UniqueName,0);
if (!SendOutSourcePin
(Reaction,0,&MessageOut,
(short)(Rt_strlen(MessageOut.data)+1),
IPC_WAITFOREVER))
RtPrintf("SinkPin 1 Handler Send Error\n");
RtPrintf("Clock %s Sent Trigger \n",
Reaction->Instance->UniqueName);
to->NextTimeout=to->LastTimeout;
}
return(TRUE);
}
SendOutSourcePinWait
#include <ComponentSpec.h> BOOL SendOutSourcePinWait ( TReactions *Reaction, unsigned int SourcePin, IPC_MSG *MessageOut, short MsgOutSize, IPC_MSG *MessageIn, short MsgInSize, long Timeout, TCommonHandler Callback );
SendOutSourcePinWait() is used to send a synchronous message out via a component instance's source (or stimulus) pin. SendOutSourcePinWait() will block until the reaction of the connected component instance's sink (or receiving) pin has issued a SendReply(). SendOutSourcePinWait() provides a callback mechanism to the connected sink pin's reaction to reply to a synchronous message.
Reaction
non-null pointer indicating the reaction generating the message
SourcePin
index of the source pin on which the message is being generated
MessageIn
buffer to hold the response message
MsgInSize
size in bytes of the buffer to hold the response message
length of time in milliseconds to wait for delivering messages that would block (e.g., in the case of a full queue). A timeout of IPC_WAITFOREVER will cause SendOutSourcePinWait() to wait until the message can be delivered to the queue of the destination sink pin.
Callback
(optional) If non-null, the value is the TCommonHandler() to use as a callback for handling the messages returned in MessageIn.
TRUE
indicates that SendOutSourcePinWait() was able to queue the message for delivery and receive acknowledgement of the message's receipt on the destination sink pin
FALSE
indicates that SendOutSourcePinWait() failed to queue the message for delivery or receive acknowledgement of the message's receipt on the destination sink pin
SendOutSourcePinWait() will fail if the component instance does not have any source pins or failed in the IPC code because of a timeout, message size error, invalid source pin ID, or unrecoverable system error.
SendReply(), SendOutSourcePin()
Example
BOOL Reaction_1_Handler
(TReactions *Reaction,TReason Reason, void * Data)
{
static DWORD Time=0;
if (Reason==PINMSG)
{
IPC_MSG MessageOut;
IPC_MSG MessageReplyRecv;
TCommonMsg *msg=(TCommonMsg *) Data;
SPrintf(MessageOut.data,
"From %s Pin %d",Reaction->Instance->UniqueName,2);
if (!SendOutSourcePinWait(Reaction, 2,
&MessageOut,(short)(Rt_strlen(MessageOut.data)+1),
&MessageReplyRecv,
IPC_MAXMSGSIZE - sizeof(IPC_HEADER),
IPC_WAITFOREVER, SinkPin_2_AnswerCallback))
RtPrintf("SinkPin 2 Handler Send Error\n");
RtPrintf("H2 %s Pin %d Received Message: %s\n",
Reaction->Instance->UniqueName,
msg->cmd,msg->MessageIn->data);
}
}
SendReply
#include <ComponentSpec.h> BOOL SendReply ( TReactions *Reaction, short src_id, IPC_MSG *MessageReply, short MsgReplySize );
SendReply() is used to send a reply to a received synchronous message via SendOutSourcePinWait(). The reaction that initiated the synchronous message will not unblock until a SendReply() is initiated from the reaction handling the sink pin to which the synchronous message was sent.
Reaction
non-null pointer indicating the reaction generating the reply message
src_id
index of the sink pin from which the reply message is being generated
MessageReply
reply message being sent
TRUE
indicates that SendReply() was able to queue the reply message for delivery on the source pin that initiated the message
FALSE
indicates that SendReply() failed to queue the reply message for delivery on the source pin that initiated the message
SendReply() will fail if the component instance does not have any sink pins or failed in the IPC code because of a message size error, invalid sink pin id, or unrecoverable system error.
SendOutSourcePinWait()
Example
BOOL Reaction_1_Handler
(TReactions *Reaction,TReason Reason, void * Data)
{
static DWORD Time=0;
if (Reason==PINMSG)
{
IPC_MSG MessageOut;
IPC_MSG MessageReplyRecv;
IPC_MSG MessageReply;
TCommonMsg *msg=(TCommonMsg *) Data;
SPrintf(MessageOut.data,
"From %s Pin %d",Reaction->Instance->UniqueName,2);
if (!SendOutSourcePinWait(Reaction, 2,
&MessageOut,(short)(Rt_strlen(MessageOut.data)+1),
&MessageReplyRecv,
IPC_MAXMSGSIZE - sizeof(IPC_HEADER),
IPC_WAITFOREVER, SinkPin_2_AnswerCallback))
RtPrintf("SinkPin 2 Handler Send Error\n");
RtPrintf("H2 %s Pin %d Received Message: %s\n",
Reaction->Instance->UniqueName,
msg->cmd,msg->MessageIn->data);
if (msg->MessageIn->header.msg_type== IPC_SENDWAIT)
{
SPrintf(MessageReply.data,
"Reply From %s Pin %d",Reaction->Instance->UniqueName,2);
SendReply(Reaction,msg->src_id,
&MessageReply,(short)(Rt_strlen(MessageReply.data)+1));
}
}
}
A.4 Component API
These functions are used by assembly controllers to manage the life cycle of component instances to perform a function specific to the assembly.
ConfigureInstance
#include <PinInterface.h> BOOL ConfigureInstance ( TComponentInstance *Instance );
ConfigureInstance() is used to allow a newly created instance of a component to initialize and perform any necessary pre-startup configuration prior to StartInstance().
TRUE
indicates that ConfigureInstance() was able to properly configure the component instance and its reactions and sink and source pins
FALSE
indicates that ConfigureInstance() failed to properly configure the component instance and its reactions and sink and source pins
The component instance may fail to properly initialize under a number of conditions, including failure to allocate necessary memory, an improperly specified number of sink or source pins, or connect to necessary IPC slots.
CreateInstance(), LoadComponent(), SetReactionTimeOut(), SetReactionPriority(), SetMeasureExecutionTime(), StartPinInterface()
Example
TComponentInstance *InstanceSimpleClock1;
...
if (ConfigureInstance(InstanceSimpleClock1)==FALSE)
{
RtPrintf
("ConfigureInstance Instance Simple Clock1 FAILED \n");
}
CreateInstance
#include <PinInterface.h> TComponentInstance* CreateInstance( struct _TPinComponent *Component, char *UniqueName, void *State, unsigned int SizeOfState );
CreateInstance() is used to create an instance of a loaded component library. The component instance must be created with a unique name and can pass initialization data or state information to the component as defined by the specific component specification. The passed initialization data or state information need not persist for the duration of the component instance's life cycle (it is the component instance's responsibility to save off this passed data).
Component
non-null pointer to heap or stack memory where CreateInstance() can store runtime-specific information about the newly created component instance
UniqueName
non-null, non-empty character string (null-terminated) that is unique among all the other component instances that have been or will be created
State
If non-null, this value is a pointer provided by the controller to data and state information that is intended to be specific to the instance of a component being created. If NULL, no data or state information was passed.
SizeOfState
If State is non-null, SizeOfState is a positive non-zero integer indicating the number of bytes in memory of State.
The component may fail to create an instance under a number of conditions, including failure to allocate necessary memory or improperly specified parameters (such as an invalid unique name).
LoadComponent(), StartPinInterface()
Example
TComponentInstance *InstanceSimpleClock1;
...
if ((InstanceSimpleClock1=CreateInstance
(PinSimpleClock, "clock1",
&SimpleClockComponentProperties[0],
sizeof(COMPONENT_SimpleClock_ARGS)))!=NULL)
{
RtPrintf("Instance clock1 Created\n");
}
else
RtPrintf("Failed to Create Instance clock1\n");
DeleteInstance
#include <PinInterface.h> BOOL DeleteInstance ( TComponentInstance *Instance );
DeleteInstance() is used to destroy an instance of a component. Once a component instance is destroyed, no further references to that instance are valid.
TRUE DeleteInstance()
was able to properly destroy the component instance and its reactions and sink and source pins.
FALSE DeleteInstance()
failed to properly destroy the component instance and its reactions and sink and source pins.
The component instance will fail only under one condition-when passing a NULL pointer.
CreateInstance()
Example
TComponentInstance *InstanceSimpleClock1; ... if (InstanceSimpleClock1) DeleteInstance(InstanceSimpleClock1);
GetNumReactions
#include <PinInterface.h> unsigned int GetNumReactions (TPinComponent *Component);
GetNumReactions() is used to read or obtain the total number of reactions supported by a component.
The passing of an invalid pointer, or a pointer initialized to something other than that returned by LoadComponent(), will fail.
LoadComponent()
Example
TPinComponent *PinSimpleClock;
PinSimpleClock=LoadComponent("SimpleClock.dll");
RtPrintf("Component has %d reactions\n",
GetNumReactions(PinSimpleClock));
GetNumSinkPins
#include <PinInterface.h> unsigned int GetNumSinkPins (TPinComponent *Component);
GetNumSinkPins() is used to read or obtain the total number of sink pins supported by a component.
non-null pointer for a component whose address space was attached by LoadComponent()
total number of sink pins supported by the component
The passing of an invalid pointer, or a pointer initialized to something other than that returned by LoadComponent(), will fail.
LoadComponent()
Example
TPinComponent *PinSimpleClock;
PinSimpleClock=LoadComponent("SimpleClock.dll");
RtPrintf("Component has %d sink pins\n",
GetNumSinkPins(PinSimpleClock));
Synopsis
#include <PinInterface.h> unsigned int GetNumSourcePins (TPinComponent *Component);
GetNumSourcePins() is used to read or obtain the total number of source pins supported by a component.
non-null pointer for a component whose address space was attached by LoadComponent()
total number of source pins supported by the component
The passing of an invalid pointer, or a pointer initialized to something other than that returned by LoadComponent(), will fail.
LoadComponent()
Example
TPinComponent *PinSimpleClock;
PinSimpleClock=LoadComponent("SimpleClock.dll");
RtPrintf("Component has %d sink pins\n",
GetNumSourcePins(PinSimpleClock));
Synopsis
#include <PinInterface.h> TReactionsInfo* GetReactionInfo ( TPinComponent *Component; unsigned int Reaction );
GetReactionInfo() is used to read or obtain the information about a specific reaction handler for a component. Indices to reactions start at 0.
Component
non-null pointer for a component whose address space was attached by LoadComponent()
Reaction
non-negative integer, which is the index into TReactionsInfo for the reaction information to be retrieved
GetReactionInfo() will return a non-null pointer to the specified reaction information for a component.
The function will fail if
- the reaction index is less than 0 or greater than or equal to the number of reactions supported by the component
- an invalid pointer, or a pointer initialized to something other than that returned by LoadComponent(), was passed
TReactionsInfo, CreateInstance()
Example
TPinComponent *PinSimpleClock;
TReactionsInfo *r;
PinSimpleClock=LoadComponent("SimpleClock.dll");
r = GetReactionInfo(PinSimpleClock, 0);
RtPrintf("Default timeout for reaction 0 is %d\n",
r->DefaultTimeOut);
GetSinkPinInfo
#include <PinInterface.h> TPinInfoSink* GetSinkPinInfo ( TPinComponent *Component; unsigned int Num );
GetSinkPinInfo() is used to read or obtain the information about a specific sink pin for a component. Indices to sink pins start at 0.
non-null pointer for a component whose address space was attached by LoadComponent()
Num
non-negative integer, which is the index into TPinInfoSink for the sink pin information needed to retrieve
GetSinkPinInfo() will return a non-null pointer to the specified sink pin information for a component.
The function will fail if
- the sink pin index is less than 0 or greater than or equal to the number of sink pins supported by the component
- an invalid pointer, or a pointer initialized to something other than that returned by LoadComponent(), was passed
TPinInfoSink, CreateInstance()
Example
TPinComponent *PinSimpleClock;
TPinInfoSink *pin;
PinSimpleClock=LoadComponent("SimpleClock.dll");
pin = GetSinkPinInfo(PinSimpleClock, 0);
RtPrintf("Name for sink pin 0 is %s\n",
pin->PinName);
Synopsis
#include <PinInterface.h> TPinInfoSource* GetSourcePinInfo ( TPinComponent *Component; unsigned int Num );
GetSourcePinInfo() is used to read or obtain the information about a specific source pin for a component. Indexes to source pins start at 0.
Component
non-null pointer for a component whose address space was attached by LoadComponent()
Num
non-negative integer, which is the index into TPinInfoSource for the source pin information to be retrieved
GetSourcePinInfo() will return a non-null pointer to the specified source pin information for a component.
The function will fail if
- the source pin index is less than 0 or greater than or equal to the number of source pins supported by the component
- an invalid pointer, or a pointer initialized to something other than that returned by LoadComponent(), was passed
TPinInfoSource, CreateInstance()