ThreadMentor supports synchronous and asynchronous one-to-one channels. This means a channel can be built and used by two threads to which this channel connects. Hence, we need to find someway for each thread to identify itself so that they can be used for channel construction. This is the concept of user-defined ID.
Each thread can be assigned with a non-negative integer identifier; however, these identifiers must be unique. Then, you must instruct the thread system to save this user-defined ID for later use. This is easy to do. Suppose 10 is the user-defined ID for a thread. Then, put the following in the constructor of that thread:
In the above, UserDefinedThreadID is a variable declared in the Thread class. After this, you can use either 10 or the value stored in UserDefinedThreadID to identify this thread.UserDefinedThreadID = 10;
To declare a synchronous (resp., asynchronous) channel, use class SynOneToOneChannel (resp., AsynOneToOneChannel). The constructor of a channel class requires three arguments: the name of the channel and the user defined IDs of the threads to which this channel connects. Once a channel is built between two threads, only these threads can send messages to and receive messages from this channel. The following builds a synchronous channel, with name "Channel15-03", between thread 15 and 3. Note that 15 and 3 are user defined thread IDs:
In some situations where a pointer to a channel is more appropriate, we can also use the following way:SynOneToOneChannel channel("Channel15-03", 15, 3);
SynOneToOneChannel *channel; channel = new SynOneToOneChannel("Channel15-03", 15, 3);
Classes SynOneToOneChannel and AsynOneToOneChannel have two methods Send() and Receive() for sending messages into and receiving messages from the channel. Two arguments are required for both methods. The first argument is a pointer to an area that contains the message to be sent or the area that will be used to store the received message. The second argument is the size of the message. For example, if we intend to send an integer value stored in variable Msg into the channel declared above, we should use one of the following forms, depending on the way the channel channel is declared.
Here, &Msg is the pointer to the area that contains the message and sizeof(int) computes the size of an integer.channel.Send(&Msg, sizeof(int)); channel->Send(&Msg, sizeof(int));
Now, suppose we wish to receive a message in an array of four integers from channel Chan. Then, we should do the following:
In fact, you can use any data structure for a message that may contain different data types. The following example shows the use of a data structure that contains a double, a int, and a char array of 100 entries:int Msg[4]; Chan.Receive(Msg, 4*sizeof(int)); Chan->Receive(Msg, 4*sizeof(int));
There is a pitfall when using messages that are not of primary types (e.g., int, char, float and double). Because the visualization system does not know the format or structure of a message, it may not be able to display the message content properly.struct Data { double x; int y; char z[100]; } Msg; Example.Send(&Msg, sizeof(Data)); Example.Receive(&Msg, sizeof(Data));