Link to home
Start Free TrialLog in
Avatar of daluu
daluuFlag for United States of America

asked on

Using threads and finite state machines to control script synchronization

Hi,

I have a question (or need for advice) on thread programming that isn't covered by the

conventional tutorials.

I'm a newbie to thread programming. I only worked on one lab project involving Windows

threads in C++ back in college. I like using C# as well but haven't gotten to thread

programming in that language.

It probably behaves like a finite state machine as well, which I've never programmed in C++

or C#. I've only used Verilog for that.

At my workplace, we have an in house tool for synchronizing the execution of certain

commands (in custom script files) using threads. The tool is based on the Intel Dialogic API

and is for phone/PBX testing. It is closely tied to the Dialogic hardware. So I am planning

on writing a subset port of the tool that supports the synchronization (the current tool has

a lot more features than that).

However, I hit some stumbling blocks:

1. The developer of the tool left years back. I managed to find the C++ source code but it

is sparsely commented, somewhat cryptic, and there is no formal documentation. It's well

object oriented but too much such that I can't find the code of interest. I'm still

attempting to analyze it when I have time.

2. The tutorials on the web for threads in C++ or C# don't seem to cover what I'm looking

for.

So I'm hoping someone here can advise me on how I should approach this and where I can find

the info necessary to build such a tool. If possible, I'd like to hear of possible

approaches in both C++ and C#. A cross-platform type of solution would be nice as well, but

I just need it for Windows for now.

Here's what I'm trying to accomplish:

We start with a script file like the following

begin script file
------------------

201; WAIT;
201; EXECUTE; "command here"
201; RELEASE; 202
...

202; EXECUTE; "command here"
202; RELEASE; 201
202; WAIT;
...
----------------
end script file

In this script, 201 & 202 execute in parallel or simultaneously. Because 201 is set to wait

state, only 202 starts initially when the script runs. Later, 202 releases 201, so it can

run. Next sequence for 202 is a wait state as well, so 201 & 202 wait on each other before

execution because the command they execute may depend on the result of the other. However,

this isn't always the case, there may be cases where 202 releases 201 and both then continue

to run as 201 initially depends on 202. And vice versa.

The script file example above is read in by the tool and parsed (into a finite state

machine?) as some data structure. Threads are created for each ID (201, 202, etc.) and the

appropriate data structure is assigned to each thread.

Throughout the lifecycle of each thread, there are 3 things it can do: wait until another

thread releases it, release another thread (by some ID), or execute a command. The command

is simply a system call to the command shell to execute an external program or script.

I can handle the script parsing, data structure setup, and command execution, but I have no

idea where or how to start on the thread synchronization. It doesn't look like a simple

mutex or semaphore will do to control the synchronization per the scripts behavior.
Avatar of peetm
peetm
Flag of United Kingdom of Great Britain and Northern Ireland image

Ok, so I'm a C/C++/Windows guy - but, when it comes to threads, I'd say if you have to use them, and learn about them, that there's no better place to start than in Java.

Honestly, have a play about with Java's abstract threads before diving into an OS's implementation!  You'll love me for this advice if you follow it!

Paul Hyde's Java Thread Programming [book] is a good resource, and one can very easily port the Java code to C++ later.

Lastly, threads are IMHO intrinsically nasty [and don't start me off on Fibers!].  I've worked on many multi-running [need a better term there] apps in the past, and all were better written as single-threaded processes that used the various inter-process mechanisms OSs supply to communicate with each other.  This also keeps the code far more modular and maintainable in my experience.

BTW, the only multi-threaded stuff I do these days is in Java [coz you'd be a dummy to get it wrong there] - else it's the multiple single-process + inter-process-communication way for me.  Works every time, and everybody's happy!
Avatar of daluu

ASKER

Thanks, Java is another alternative language to use. But then how would I solve the issue of having a thread waiting to be released by another thread or a thread releasing another thread, something like:

some code for thread A will at some point call wait(). And it waits until it is released by any thread that releases it.

And some code in thread B will at some point call something like this release(idOfThreadB). and that release/resume threadB. The ID is either a reference to thread B's handle or some unique ID that can be used to release threadB.

If this is feasible in Java, C++, or C#, then I can start R&D, otherwise, I'll need to find a solution/framework before continuing.

I don't think what I want can be done without multiple processes or threads as I must run several tasks in parallel that must wait on other tasks at certain points in time.
>>>> In this script, 201 & 202 execute in parallel or simultaneously.
I can't see that from your description. It looks like thread execution runs exclusively. If so, you need no threads. Just do the 'jobs' into a queue and process the queue using one thread.

If I am right, you have at most two threads. A main thread which reads the script and initially fills the job queue. Then a worker thread which processes the queue. While the worker thread is running the main thread could wait for user input and/or monitor the worker thread's activitities, maybe puuing some more jobs into the job queue. For that - adding to the queue and removing from queue - you would need thread synchronisation simpliest made by a critical section resource.

Regards, Alex
SOLUTION
Avatar of NovaDenizen
NovaDenizen

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of daluu

ASKER

Thanks for the recent comments, especially from Dorfer32 and NovaDenizen. I will look into your suggestions and try the code sample posted.

A brief update on new findings and responses to comments:

1. NovaDenizen brought up good concerns that were addressed by the old/original tool that I will have to address as well. The initial post was for a simple case. The script can support more than 2 devices/threads--the wait command is the same as posted but the release command supports multiple threads like

201; RELEASE; 202; 203; 204

In the original tool, calling release on a thread that isn't waiting (or before it goes into waiting) will have no effect, it continues to run. But if the corresponding release is called before the wait, the waiting thread will be stuck and the program will have to be terminated and re-run to fix the problem. This is expected though as the input script should be written correctly in the first place. The program only executes what is specified in the input script.


2. I analyzed the original source code a bit yesterday and found some useful information, but still not enough for me. The snippets below relate to the wait and release functions and it appears to be using semaphores with events? Unfortunately, the code is so abstracted that I haven't pinpointed where or how the code snippets tie into the rest of the program's code. If you have some insight on this, I would appreciate it.

//relevant code in function that signals thread to wait
//...
stringstream ss;
ss << fDevice.fName << "; CMD" << "; Wait; ";
if (-1 == fTimeOut) {
    ss << "infinite";
} else {
    ss <<  fTimeOut;
}
//...
HANDLE ha[2];
ha[0] = fDevice.fCfg.fStopEvt;
ha[1] = fDevice.fWaitEvent;
WaitForMultipleObjects(2, ha, FALSE, fTimeOut*1000);
ResetEvent(fDevice.fWaitEvent);

ss.str("");
ss << fDevice.fName << "; RET" << "; Wait; Released";
//...
return true;


//relevant code in function that signals thread to release some other waiting thread
stringstream ss;
ss << fDevice.fName << "; CMD" << "; Release";

int size = fRelease.size();
for (int x=0; x < size; x++) {
    ss << "; " << fRelease[x]->fName;
    SetEvent(fRelease[x]->fWaitEvent);
}
//...
return true;
Avatar of daluu

ASKER

Thanks for the code sample Dorfer32. This is something I can work with. Easy to follow as well.

I'm going to start working with it and see how well that goes.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of daluu

ASKER

Thanks for the analysis. I was thinking it was something like that. I knew the stringstream code was for logging and kept it with the code snippet for reference.

While on the subject, can you or someone point me to books or online articles about using events for synchronization in C++? I'd like to learn more and also to compare with events in C#.
eventhandling is not difficult. You create an event calling CreateEvent, set it by SetEvent and release it by ReleaseEvent. Look for example at

http://msdn2.microsoft.com/en-us/library/ms686211.aspx to learn more.

Regards, Alex