I want to implement a state machine that will periodically monitor some status data (the status of my system) and react to it.
This seems to be something quite basic for a state machine (I've had this problem many times before), but I could not find a good way to do it. Here is some pseudo code to explain what I'd like to achieve:
// some data that is updated from IOs for example
MyData data;
int state = 0;
while( true ) {
update( & data ); //read a packet from serial port
//and update the data structure
switch( state ) {
case 0:
if( data.field1==0 ) state = 1;
else doSomething();
break;
case 1:
if( data.field2>0 ) state = 2;
else doSomethingElse();
break;
// etc.
}
usleep(100000); //100ms
}
Of course on top of that, I want to be able to execute some actions upon entering and exiting a state, maybe do some actions at each iteration of the state, have substates, history, etc. Which is why this simplistic approach quickly becomes impractical, hence boost statechart.
I've thought about some solutions, and I'd like to get some feedback.
1) I could list all my conditions for transitions and create an event for each one. Then I would have a loop that would monitor when each of those boolean toggles. e.g. for my first condition it could be:
if( old_data.field1!=0 && new_data.field1==0 )
// post an event of type Event 1
but it seems that it would quickly become difficult
2) have a single event that all states react to. this event is posted whenever some new status data is available. As a result, the current state will examine the data and decide whether to initiate a transition to another state or not
3) have all states inherit from an interface that defines a do_work(const MyData & data) method that would be called externally in a loop, examine the data and decide whether to initiate a transition to another state or not
Also, I am opened to using another framework (i.e. Macho or boost MSM)
Having worked with boost MSM, statecharts and QP my opinion is that you are on the right track with statecharts. MSM is faster but if you don't have much experience with state machines or meta programming the error messages from MSM are hard to understand if you do something wrong. boost.statecharts is the cleanest and easiest to understand. As for QP its written in embedded style (lots of preprocessor stuff, weaker static checking) although it also works in a PC environment. I also believe its slower. It does have the advantage of working on a lot of small ARM and similar processors. Its not free for commercial use as opposed to boost solutions.
Making an event for every type of state change does not scale. I would make one type of event EvStateChanged give it a data member containing a copy or reference to the dataset (and maybe one to the old data if you need it). You can then use costume reactions to handle whatever you need from any state context. Although default transitions work quite well in a toaster oven context (which are often used to demonstrate SM functionality) most real world SMs I have seen have many custom reactions, don't be shy to use them.
I don't really understand enough about your problem to give a code example but something along the lines of:
while( true ) {
update( & data ); //read a packet from serial port
//and update the data structure
if(data != oldData){
sm.process_event(EvDataChanged(data,oldData));
}
else{
timeout++;
if(timeout>MAX_TIMEOUT)
sm.process_event(EvTimeout());
}
usleep(100000); //100ms
}
and then handle your data changes in custome reactions depending on state along these lines:
SomeState::~SomeState(){
DoSomethingWhenLeaving();
}
sc::result SomeState::react( const EvDataChanged & e){
if(e.oldData.Field1 != e.newData.Field1){
DoSomething();
return transit<OtherState>();
}
if(e.oldData.Field2 != e.newData.Field2){
return transit<ErrorState>(); //is not allowed to change in this state
}
if(e.oldData.Field3 == 4){
return forward_event(); //superstate should handle this
}
return discard_event(); //don't care about anything else in this context
}
Related
i'm studying this source base. Basically this is an Anim server client for Symbian 3rd edition for the purpose of grabbing input events without consuming them in a reliable way.
If you spot this line of the server, here it is basically setting the RProperty value (apparently to an increasing counter); it seems no actual processing of the input is done.
inside this client line, the client is supposed to be receiving the notification data, but it only calls Attach.
my understanding is that Attach is only required to be called once, but is not clear in the client what event is triggered every time the server sets the RProperty
How (and where) is the client supposed to access the RProperty value?
After Attaching the client will somewhere Subscribe to the property where it passes a TRequestStatus reference. The server will signal the request status property via the kernel when the asynchronous event has happened (in your case the property was changed). If your example source code is implemented in the right way, you will find an active object (AO; CActive derived class) hanging around and the iStatus of this AO will be passed to the RProperty API. In this case the RunL function of the AO will be called when the property has been changed.
It is essential in Symbian to understand the active object framework and quite few people do it actually. Unfortunately I did not find a really good description online (they are explained quite well in Symbian OS Internals book) but this page at least gives you a quick example.
Example
In the ConstructL of your CMyActive subclass of CActive:
CKeyEventsClient* iClient;
RProperty iProperty;
// ...
void CMyActive::ConstructL()
{
RProcess myProcess;
TSecureId propertyCategory = myProcess.SecureId();
// avoid interference with other properties by defining the category
// as a secure ID of your process (perhaps it's the only allowed value)
TUint propertyKey = 1; // whatever you want
iClient = CKeyEventsClient::NewL(propertyCategory, propertyKey, ...);
iClient->OpenNotificationPropertyL(&iProperty);
// ...
CActiveScheduler::Add(this);
iProperty.Subscribe(iStatus);
SetActive();
}
Your RunL will be called when the property has been changed:
void CMyActive::RunL()
{
if (iStatus.Int() != KErrCancel) User::LeaveIfError(iStatus.Int());
// forward the error to RunError
// "To ensure that the subscriber does not miss updates, it should
// re-issue a subscription request before retrieving the current value
// and acting on it." (from docs)
iProperty.Subscribe(iStatus);
TInt value; // this type is passed to RProperty::Define() in the client
TInt err = iProperty.Get(value);
if (err != KErrNotFound) User::LeaveIfError(err);
SetActive();
}
I made a class that has an asynchronous OpenWebPage() function. Once you call OpenWebPage(someUrl), a handler gets called - OnPageLoad(reply). I have been using a global variable called lastAction to take care of stuff once a page is loaded - handler checks what is the lastAction and calls an appropriate function. For example:
this->lastAction == "homepage";
this->OpenWebPage("http://www.hardwarebase.net");
void OnPageLoad(reply)
{
if(this->lastAction == "homepage")
{
this->lastAction = "login";
this->Login(); // POSTs a form and OnPageLoad gets called again
}
else if(this->lastAction == "login")
{
this->PostLogin(); // Checks did we log in properly, sets lastAction as new topic and goes to new topic URL
}
else if(this->lastAction == "new topic")
{
this->WriteTopic(); // Does some more stuff ... you get the point
}
}
Now, this is rather hard to write and keep track of when we have a large number of "actions". When I was doing stuff in Python (synchronously) it was much easier, like:
OpenWebPage("http://hardwarebase.net") // Stores the loaded page HTML in self.page
OpenWebpage("http://hardwarebase.net/login", {"user": username, "pw": password}) // POSTs a form
if(self.page == ...): // now do some more checks etc.
// do something more
Imagine now that I have a queue class which holds the actions: homepage, login, new topic. How am I supposed to execute all those actions (in proper order, one after one!) via the asynchronous callback? The first example is totally hard-coded obviously.
I hope you understand my question, because frankly I fear this is the worst question ever written :x
P.S. All this is done in Qt.
You are inviting all manner of bugs if you try and use a single member variable to maintain state for an arbitrary number of asynchronous operations, which is what you describe above. There is no way for you to determine the order that the OpenWebPage calls complete, so there's also no way to associate the value of lastAction at any given time with any specific operation.
There are a number of ways to solve this, e.g.:
Encapsulate web page loading in an immutable class that processes one page per instance
Return an object from OpenWebPage which tracks progress and stores the operation's state
Fire a signal when an operation completes and attach the operation's context to the signal
You need to add "return" statement in the end of every "if" branch: in your code, all "if" branches are executed in the first OnPageLoad call.
Generally, asynchronous state mamangment is always more complicated that synchronous. Consider replacing lastAction type with enumeration. Also, if OnPageLoad thread context is arbitrary, you need to synchronize access to global variables.
I'm trying to make a kernel simulation as my DSA (data structure and algorithm) project in C++. There will be different modules(process manager, memory manager etc.) in it. Right now i have to make a Process Manager and I've only a little a idea about it (like, i can use a queue). Can anyone help me how can i make a process manager in c++.
First make a scheduler (unless you understand "process manager" as what is commonly known as a "scheduler".) you must decide upon multitasking model, cooperative vs preemptive. Preemptive may be difficult - use some kind of interrupts and so on... may be unnecessarily complex for a school project.
If you don't know which model to pick, I strongly suggest cooperative multitasking. It is where each process takes a certain small slice of time, then returns control to the scheduler by itself - say, after going through one iteration of its "main loop". Usually done by the main loop calling some kind of "task()" function of the process-class, and the task() ending with a 'return', with no long loops underway.
Start with a model of a "task/process". Should it be loadable (say, as a shared object file), or predefined at startup (a class). Entry point, persistent state storage, "main loop" routine with a finite state machine (usually implemented as a switch that moves between various states). The task works by repeatedly launching the "entry point" routine.
The states to be implemented will likely be:
init, launched on startup, once
idle - check for requests for activity, if none, return control
various "work" states.
Once you have that, prepare a dynamic queue of such tasks. Adding, removing, iterating, elevated priority = call out of order, and so on. The "scheduler" iterates through all the tasks and starts the "startup routine" of each of them.
When you have that ready, you can write what is commonly known as "task manager" - a program that edits the list. Remove a program from the queue, add a new one, change priority, pause etc.
To help you imagine, you currently usually write:
int main()
{
do_something1();
do_something2();
}
void do_something1()
{
//initialize
...perform stuff
int x=0;
//main loop
do {
if(condition...) {
...perform stuff
} else {
...perform other stuff
blargh(x);
x++;
}
} while(!end);
//ending
//finish...
...mop up.
}
What you need to write:
int main()
{
//main loop
do {
do_something1();
do_something2();
} while(!global_end);
}
void do_something1()
{
static state_enum state = STATE_INI;
static int x=0;
switch(state)
{
case STATE_INI:
//initialize
...perform stuff
state = STATE_WORK1;
x=0;
break;
case STATE_WORK1:
//main loop, mode 1
...perform stuff
if(condition) state = STATE_WORK2;
if(condition2) state = STATE_END;
if(condition4) state = STATE_IDLE;
break;
case STATE_WORK2:
//main loop, mode 2
...perform stuff
blargh(x);
x++;
if(condition3) state = STATE_WORK1;
if(condition4) state = STATE_IDLE;
break;
case STATE_IDLE:
//do nothing
//don't do any stuff.
if(any_condition) state = STATE_WORK1;
break;
case STATE_END:
//finish...
...mop up.
break;
}
return;
}
...and your process manager will be replacing what constitutes static calls to
do_something1();
do_something2();
with a dynamic list of functions to call.
fyi, writing apps for preemptive scheduling system is much easier, you just write them like in the first version, never worrying about preserving state between calls (static), or returning control, or keeping each case statement short and sweet with very short, if any loops inside, unrolling bigger ones. But writing the scheduler itself, interrupting a program and saving its state, then restoring it and resuming from where it interrupted is much, much harder.
A process manager manages processes. Obviously, to refine that, you first need to define what constitutes a process in your OS. There's no reason for a process manager to deal with threads when all your processes are single-threaded, for instance. And if you don't have virtual memory, that doesn't need to be managed either.
You did note that you'd have a memory manager. This is certainly possible outside the process manager, but you would need to define the interface between them. For instance, the process manager would need to allocate memory to load the program code on startup; the program itself cannot do that (chicken and egg problem).
How are multithreaded game servers written?
If there are 4 threads, is there one thread running the game loop, and 3 accepting and processing requests? Also: is information sent from the thread running the game loop?
Starkey already pointed out that it depends a whole lot on the precise design.
For instance, on games with many clients, you'd assign dedicated threads to handling input, but for games with a few clients (say <=16) there's no need for multiple threads.
Some games feature NPC's with considerable smarts. It may be smart to run those on their own threads, but if you have too many you'll need a threadpool so a bunch of NPC's can share a single thread.
If you've got a persistent world, you'll need to write out state to a hard disk somewhere (probably via a DB). Since that has serious latencies, you won't want to have a main game loop wait on that I/O. That will be another thread, then.
Finally, there's the question whether you even have a main game loop. Would a MMO have a single loop, or would you rather have many ?
The main key is to make sure your game logic is not affected by your threading model.
As such, most game servers look something like this:
main() {
gGlobalReadOnlyStuff = LoadReadOnlyStuff();
SpawnThreads(numCores); // could be another limiting resource...
WaitForThreadsToBeReadyToGo();
while(1) {
WaitForNetworkInput(networkInput);
switch(networkInput.msg) {
case ADMIN_THING: // start/stop websever, dump logs, whatever...
DoAdminThing(networkInput.params);
break;
case SPAWN_GAME: // replace 'game' with 'zone' or 'instance' as needed
idThread = ChooseBestThread(); // round robin, random, etc
PostStartGameMessageToThread(idThread, networkInput.msg);
break;
// ...
}
}
}
void ThreadUpdate() {
threadLocalStuff = LoadThreadLocalStuff();
SignalThreadIsReadyToGo();
while(1) {
lock(myThreadsMessageQueue);
// copy messages to keep lock short
localMessageQueue = threadsMessageQueue;
unlock(myThreadsMessageQueue);
foreach(message in localMessageQueue) {
switch(message.msg) {
case SPAWN_GAME:
threadLocalStuff.games.MakeNewGame(message.params));
break;
case ADMIN_THING__LET_EVERYONE_KNOW_ABOUT_SERVER_RESET:
...;
break;
// etc...
}
}
foreach(game in threadLocalStuff.games) {
game.Update(); // game will handle its own network communication
}
}
The two hard things then are 'coming up with a partition (game, zone, instance, whatever) appropriate for you game' and 'transitioning things (players, fireballs, epic lootz) across those boundaries' One typical answer is "serialize it through a database", but you could use sockets/messages/files/whatever. But yeah, where and how to make these partitions and minimizing what can go across the boundaries is intimately tied to your game design.
(And yes, depending on your setup, there are possibly a few 'shared' systems (logging, memory) that may need a multithreading treatment(or even better, just have one logger/heap per thread))
I am writing a framework for an embedded device which has the ability to run multiple applications. When switching between apps how can I ensure that the state of my current application is cleaned up correctly? For example, say I am running through an intensive loop in one application and a request is made to run a second app while that loop has not yet finished. I cannot delete the object containing the loop until the loop has finished, yet I am unsure how to ensure the looping object is in a state ready to be deleted. Do I need some kind of polling mechanism or event callback which notifies me when it has completed?
Thanks.
Usually if you need to do this type of thing you'll have an OS/RTOS that can handle the multiple tasks (even if the OS is a simple homebrew type thing).
If you don't already have an RTOS, you may want to look into one (there are hundreds available) or look into incorporating something simple like protothreads: http://www.sics.se/~adam/pt/
So you have two threads: one running the kernel and one running the app? You will need to make a function in your kernel say ReadyToYield() that the application can call when it's happy for you to close it down. ReadyToYield() would flag the kernel thread to give it the good news and then sit and wait until the kernel thread decides what to do. It might look something like this:
volatile bool appWaitingOnKernel = false;
volatile bool continueWaitingForKernel;
On the app thread call:
void ReadyToYield(void)
{
continueWaitingForKernel = true;
appWaitingOnKernel = true;
while(continueWaitingForKernel == true);
}
On the kernel thread call:
void CheckForWaitingApp(void)
{
if(appWaitingOnKernel == true)
{
appWaitingOnKernel = false;
if(needToDeleteApp)
DeleteApp();
else
continueWaitingForKernel = false;
}
}
Obviously, the actual implementation here depends on the underlying O/S but this is the gist.
John.
(1) You need to write thread-safe code. This is not specific to embedded systems.
(2) You need to save state away when you do a context switch.