The User-Contributed library consists of general-purpose, re-usable, models contributed by various users. They are offered for sharing in the hope that they may be useful to others. The User-Contributed models are included with all CSIM distribution packages under the $CSIM_MODEL_LIBS/user_contributed directory. If you develop functions or models that may be useful to other projects, please consider contributing them.
Because each button has a unique box and link associated with it, you can add many buttons to your diagram. Your model can determine which button was pressed by which link receives the token. It is recommended to make each button-box smaller than the button which will cover it.
The slider-box accepts four attributes:
Because each slider has a unique box and link associated with it, you can add many sliders to your diagram. Your model can determine which slider was moved by which link receives the token. It is recommended to make each slider-box smaller than the slider which will cover it.
To use it, include (by-reference) the $CSIM_MODEL_LIBS/user_contributed/named_synchron.sim file in one of your model files. Consider a model with boxes A, B, C, and D. Assume and A and B want to share a synchron, and C and D wish to share another synchron. Boxes A and B need to come up with a common name for their synchron, say "S1", and C and D likewise need a common -- but distinct -- name for their's, say "S2".
The code within boxes A and B, could be:
SYNCHRON **x;Then they can WAIT or RESUME on x. For example:x = Get_Named_Synchron( "S1" );
WAIT( x, QUEUABLE );
While the code in C and D, could be:
SYNCHRON **x;Again, they then could WAIT or RESUME on their x synchron. For example:x = Get_Named_Synchron( "S2" );
RESUME( x, QUEUABLE );
How It Works:
The named-synchron object maintains a global list of 'registered' synchrons by character-string names. When anyone asks for a name which has not been used, it allocates a new synchron, adds it (and it's name) to the list, and returns the new synchron's address. When anyone asks for a name that has already been allocated, it finds it in the list, and returns that synchron's address.
Think of this as a rendezvous method. The synchron-list is like a central message-board or white-board where everyone goes to meet-up.
Just include named_synchron.sim to your model and then call Get_Named_Synchron(xxx) where you need it.
Download a simple Example. (Right-click to Save-As.)
This implementation is general-purpose and dynamic, in that it does not need to be changed when different message-names are used. The pub/sub service works through a call-back process, where subscribers mention the message-name and function to be called (call-back) when activated. When a new subscription is registered, a waiting-call is set, to wake up the generic_subscriber thread. Into the Thread_Var is passed the call-back address, and an optional parameter. The generic_subscriber thread re-sets the waiting-call before dying. An ability to unsubscribe is also included.
The following routines are provided:
struct genpubsub_subscription *generic_message_subscribe( char *message_name, gpsm_callback callback, void *param ) - Subscribe to callback to messages of given name. Inputs: Message_Name - Message to be sensitive to. CallBack - Function to be called when message arrives. Param - Arbitrary parameter or structure pointer to be passed to callback function. Return Value: Subscription - Can be used to cancel subscription. struct NamedMessageQueue *generic_message_publish( char *message_name, void *mdata ) - Publish data to a message of given name. Inputs: Message_Name - Message-queue to post message to. MData - Data to be passed to subscribing function(s). Output: Return-Value - Synchron pointer to message-queue, for use with future calls to generic_message_publish_quick(...). void generic_message_publish_quick( struct NamedMessageQueue *mqueue, void *mdata ) - Publish data to cached message-queue. Like generic_message_publish above, but quicker. Avoids repeated name-lookups by using the handle returned from first call to generic_message_publish. Inputs: Message_Queue_Handle - Synchron pointer to message-queue. MData - Data to be passed to subscribing function(s). Output: (none) void *generic_message_unsubscribe( char *message_name, struct genpubsub_subscription *subscription ) - Removes given subscription from named message queue. Inputs: Message_Name - Message-queue name. subscription - Subscription-ID returned generic_message_subscribe. Output: (none) Examples: generic_message_subscribe( "message3", (gpsm_callback)myroutineABC, "Three" ); generic_message_publish( "message1", "data_A" );'
How it works: Applications "send-messages" by resuming "named-synchrons", and receive messages by waiting for "named-synchrons". The "named-synchron" service is a generic rendezvous method based on a centralized message-name-list. When a named-synchron is accessed, the name is looked-up from the list. If not found, a new synchron is allocated, initialized, and added to the list with its name. In either case, if it was found or not, the corresponding synchron is returned for resuming (publishers) or waiting-on (subscribers).
The directory contains a simple test-example of pub/sub messaging, test.sim.
Files:
generic_messenger.sim - Generic messaging service models.
Supports any messages without being changed.
test.sim - Example of using above services.
To try:
csim test.sim
./sim.exe -batch
Or, from GUI:
gui test.sim
Tools / Build Sim
Tools / Run Sim
There are two versions: long and short term synchronizers. (Called Real_Time_Synchronizer_Shortterm and Real_Time_Synchronizer_Longterm, respectively.) Under most situations there will be little or no difference between them. However, if the simulator ever falls behind momentarily:
The synchronizer models have one attribute: synch_granularity. It controls the granularity at which simulation time is controlled to match real-time. It accepts a value in seconds. By default, the synch_granularity is set to 0.2 seconds, or one-fifth of a second. This is a reasonable value for many applications. Larger values enable slighlty greater efficiency. Values down to 1/100th second can often be maintained accurately and relatively efficiently, depending on the simulation model.