threading changed.

origin
steffen 5 years ago
parent 22d750a63a
commit b5a6396a18

@ -1,9 +1,9 @@
2021-01-19:
- threading should be now more stable no deadlocks
2021-01-15:
- web interface for block assignemt seems ready
- saving and loading data from a block.
:q
:q
:q!
2020-12-05:
- locomotive fixed division by zero

@ -158,12 +158,15 @@ int Locomotives::Change(Locomotive *loco) {
if (locomotives[i].name[0] != 0) {
// found element
if (strncmp(locomotives[i].name, loco->name, REFERENCENAME_LEN) == 0) {
// copy block data
ifree = i;
break;
}
}
else if (ifree == -1) ifree = i;
}
// element not found add new element
if (ifree != -1 && ifree < max) {
locomotives[ifree] = *loco;
@ -279,7 +282,8 @@ int Locomotives::SetDestination (string name, string block, int direction) {
int Locomotives::SetAssign (string name, string block, int direction) {
int i;
int i, x = -1;
int y = -1;
Lock();
for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0)
@ -291,13 +295,19 @@ int Locomotives::SetAssign (string name, string block, int direction) {
}
UnLock();
while (server->railways.FindReference(&x, &y, block)) {
printf ("%s:%d Reference found at %d, %d\n", __FILE__, __LINE__, x, y);
}
printf ("%s:%d %s ************** finish me **************\n", __FILE__, __LINE__, __FUNCTION__);
return 1;
}
int Locomotives::Reset(string name) {
Railway rw;
int i;
JSONParse jp;
Lock();
for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0)
@ -309,37 +319,73 @@ int Locomotives::Reset(string name) {
locomotives[i].blocknext[0] = 0;
break;
}
server->railways.ClearLockedby(name);
UnLock();
printf ("%s:%d %s ************** finish me **************\n", __FILE__, __LINE__, __FUNCTION__);
return 1;
};
int Locomotives::SetMan(string name) {
int i;
printf ("%s:%d %s ************** finish me **************\n", __FILE__, __LINE__, __FUNCTION__);
Lock();
for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0)
if (name.compare(locomotives[i].name) == 0) {
debug (0, "Locomotives::SetMan (Name:%s)\n", name.c_str());
locomotives[i].flags &= ~(LOCO_F_AUTO | LOCO_F_AUTOSTOP | LOCO_F_RANDOM);
break;
}
UnLock();
SetSpeed(name, 0);
return 1;
};
int Locomotives::SetAutoMan(string name) {
int i;
printf ("%s:%d %s ************** finish me **************\n", __FILE__, __LINE__, __FUNCTION__);
Lock();
for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0)
if (name.compare(locomotives[i].name) == 0 && (locomotives[i].flags & LOCO_F_AUTO)) {
debug (0, "Locomotives::SetAutoMan (Name:%s)\n", name.c_str());
locomotives[i].flags |= LOCO_F_AUTOSTOP;
locomotives[i].flags &= ~LOCO_F_RANDOM;
break;
}
UnLock();
return 1;
};
int Locomotives::SetAuto(string name) {
int i;
printf ("%s:%d %s ************** finish me **************\n", __FILE__, __LINE__, __FUNCTION__);
Lock();
for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0)
if (name.compare(locomotives[i].name) == 0) {
debug (0, "Locomotives::SetAuto (Name:%s)\n", name.c_str());
locomotives[i].flags |= LOCO_F_AUTO;
break;
}
UnLock();
return 1;
};
int Locomotives::SetAutoRand(string name) {
int i;
printf ("%s:%d %s ************** finish me **************\n", __FILE__, __LINE__, __FUNCTION__);
Lock();
for (i = 0; i < max; i++) if (locomotives[i].name[0] != 0)
if (name.compare(locomotives[i].name) == 0 && (locomotives[i].flags & LOCO_F_AUTO)) {
debug (0, "Locomotives::SetRandom (Name:%s)\n", name.c_str());
locomotives[i].flags |= LOCO_F_RANDOM;
locomotives[i].flags &= ~LOCO_F_AUTOSTOP;
break;
}
UnLock();
return 1;
};

@ -20,6 +20,26 @@ enum {
LOCO_INT_DCC128
};
enum {
LOCO_OR_NOTHING = 0,
LOCO_OR_SEARCH, // search way (to next block and lock way)
LOCO_OR_PREPARE, // switch turnouts right way (one every 100ms)
// if no turnout has to be set, continue
LOCO_OR_ONTHEWAY, // locomotive is on the way // maybe prepare next block?
// ASSIGN -> PREV, NEXT -> ASSIGN, NEXT <- (empty)
// propabely searching next block (if DEST is set)?
LOCO_OR_ONTHEWAYPREPARE, // prepare way as long as on the way
LOCO_OR_ENTERBLOCK, // got new block ready?
// if NEXT is empty and way not AutoPrepareWay not finished... slow down
LOCO_OR_STOP, // stopping
LOCO_OR_WAIT // wait some time
};
struct s_LocoAuto {
int onroute; // LOCO_OR_.....
struct timeval waituntil; // wait until this time for next action (tournout, waiting station...)
};
struct s_Locomotive {
char name[REFERENCENAME_LEN]; // name
char ifname[REFERENCENAME_LEN]; // ref. of interface
@ -39,6 +59,8 @@ struct s_Locomotive {
char blocknext[REFERENCENAME_LEN]; // next block to go to
char blockprev[REFERENCENAME_LEN]; // prev block (mostly assigned block
char blockdest[REFERENCENAME_LEN]; // destination block
int auto_onroute; // LOCO_OR_....
} typedef Locomotive;
class Locomotives {

@ -31,34 +31,27 @@ Network::Network() {
thread_running = 0;
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
mtxsessions = { 0 };
mtxsessions = PTHREAD_MUTEX_INITIALIZER;
}
Network::~Network() {
list<Session*>::iterator iter;
LockSessions();
while ((iter = sessions.begin()) != sessions.end()) {
Session *s = *iter;
sessions.remove(*iter);
delete s;
}
UnLockSessions();
Stop();
};
int Network::LockThread() {
if (pthread_mutex_lock(&mtx) == 0) return 1;
else return 0;
}
int Network::UnLockThread() {
if (pthread_mutex_unlock(&mtx) == 0) return 1;
else return 0;
}
void Network::ThreadProcess() {
list<UNIX*>::iterator iteru;
Session *s;
@ -146,21 +139,17 @@ void Network::Stop() {
}
void Network::_ChangeListPushToAll(string changes) {
void Network::ChangeListPushToAll(string changes) {
list<Session*>::iterator iter;
LockSessions();
for (iter = sessions.begin(); iter != sessions.end(); iter++) {
if ((*iter)->GetSessionID() > 0) (*iter)->ChangeListPush(changes);
}
UnLockSessions();
};
void Network::ChangeListPushToAll(string changes) {
LockThread();
_ChangeListPushToAll(changes);
UnLockThread();
};
int Network::ServerLoop() {
UNIX *u = NULL;
@ -178,12 +167,14 @@ Session *Network::GetSession(int sid) {
Session *s = NULL;
list<Session*>::iterator iter;
LockSessions();
for (iter = sessions.begin(); iter != sessions.end(); iter++) {
if ((*iter)->GetSessionID() == sid) {
s = *iter;
break;
}
}
UnLockSessions();
return s;
};
@ -247,12 +238,12 @@ int Network::ClientLoop(UNIX *client) {
debug (0, "* sid not set, gettin new SID");
session = new Session(rid);
sid = session->GetSessionID();
LockThread();
LockSessions();
sessions.push_back(session);
UnLockThread();
UnLockSessions();
}
else {
LockThread();
LockSessions();
//
// search for session
session = NULL;
@ -262,16 +253,14 @@ int Network::ClientLoop(UNIX *client) {
break;
}
}
UnLockThread();
UnLockSessions();
}
if (session) {
JSONElement je;
int retval;
LockThread();
retval = session->ProcessData(&json, &jsonout);
UnLockThread();
len = BUFFERSIZE;
if (retval) {

@ -11,6 +11,7 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
@ -28,7 +29,7 @@ using namespace std;
#include "modelbahn.h"
#include "json.h"
#include "debug.h"
extern int next_sessionID;
@ -38,6 +39,12 @@ private:
int sessionID;
int randomID;
list<string> changes;
pthread_mutex_t mtxchanges;
// void LockChanges() { debug (0," ****** %s ", __FUNCTION__); pthread_mutex_lock(&mtxchanges); };
// void UnLockChanges() { pthread_mutex_unlock(&mtxchanges); debug (0," ****** %s ", __FUNCTION__); };
void LockChanges() { pthread_mutex_lock(&mtxchanges); };
void UnLockChanges() { pthread_mutex_unlock(&mtxchanges); };
void AddJSONRailway(JSONParse *jp);
void DelJSONRailway(JSONParse *jp);
@ -91,6 +98,8 @@ class Network {
private:
void ThreadProcess();
pthread_mutex_t mtx;
pthread_mutex_t mtxsessions;
pthread_t thread;
int thread_running;
@ -102,14 +111,15 @@ private:
int ClientLoop(UNIX *u);
UNIX sockserver;
void _ChangeListPushToAll (string changes); // not thread save
friend class Session;
public:
Network();
~Network();
int LockThread();
int UnLockThread();
void Lock() { pthread_mutex_lock(&mtx); };
void UnLock() { pthread_mutex_unlock(&mtx); };
void LockSessions() { pthread_mutex_lock(&mtxsessions); };
void UnLockSessions() { pthread_mutex_unlock(&mtxsessions); };
int Start();
void Stop();

@ -96,7 +96,7 @@ JSONParse Railways::GetJSONRailway(int x, int y) {
Railway Railways::GetRailwayFromJSON(JSONParse *j) {
string name;
string text;
Railway r = {
type: RAILWAY_NOTHING,
x: 0,
@ -104,9 +104,11 @@ Railway Railways::GetRailwayFromJSON(JSONParse *j) {
dir: 0,
altdir: 0,
maxspeed: -1,
flags: 0
flags: 0,
name: { 0 }
};
r.name[0] = 0;
r.lockedby[0] = 0;
j->GetValueInt("x", &r.x);
j->GetValueInt("y", &r.y);
@ -115,8 +117,10 @@ Railway Railways::GetRailwayFromJSON(JSONParse *j) {
j->GetValueInt("type", &r.type);
j->GetValueInt("maxspeed", &r.maxspeed);
j->GetValueInt("flags", &r.flags);
j->GetValue("name", &name);
strncpy (r.name, name.c_str(), REFERENCENAME_LEN);
j->GetValue("name", &text);
strncpy (r.name, text.c_str(), REFERENCENAME_LEN);
j->GetValue("lockedby", &text);
strncpy (r.lockedby, text.c_str(), REFERENCENAME_LEN);
return r;
};
@ -295,5 +299,54 @@ Railway Railways::Get(int x, int y) {
return r;
};
void Railways::ClearLockedby(string name) {
int x, y;
JSONParse jp;
Lock();
for (x = 0; x < width; x++)
for (y = 0; y < height; y++) {
if (name.compare(railways[GetRIdx(x,y)].lockedby) == 0) {
railways[GetRIdx(x,y)].lockedby [0] = 0;
changed = 1;
jp.AddObject("railway",_GetJSONRailway(x,y));
if(network) network->ChangeListPushToAll(jp.ToString());
}
}
UnLock();
}
int Railways::FindReference(int *x, int *y, string name) {
int found = 0;
if (x == NULL || y == NULL) return 0;
if (*x < 0 || *y < 0) {
*x = 0;
*y = 0;
}
Lock();
for (; found == 0 && *y < height; (*y)++) {
if (*x >= width) *x = 0;
else (*x)++;
for (; found == 0 && *x < width; (*x)++) {
if (strncmp (railways[GetRIdx(*x, *y)].name, name.c_str(), REFERENCENAME_LEN) == 0) {
found = 1;
break;
}
}
}
UnLock();
if (*x < width && *y < height) return 1;
else return 0;
};
int FindWay(string blockstart, string blockend, string lockedfor, string *next) {
return 0;
};

@ -64,6 +64,7 @@ class Railways {
int changed;
pthread_mutex_t mtx;
int Lock();
int UnLock();
int GetRIdx(int x, int y);
@ -86,11 +87,16 @@ class Railways {
void ClearChanged() { changed = 0; };
int Change(Railway *rw);
Railway RailwayGet(int x, int y) {return railways[GetRIdx(x, y)];};
void ClearLockedby(string name);
Railway RailwayGet(int x, int y) {return railways[GetRIdx(x, y)];}; // no lock
JSONParse GetJSONRailway(int x, int y);
JSONParse GetJSONTrack();
void GetJSONAll(JSONParse *json);
Railway GetRailwayFromJSON(JSONParse *j);
int FindReference(int *x, int *y, string name);
int FindWay(string blockstart, string blockend, string lockedfor, string *next);
};
#endif

@ -9,7 +9,11 @@ int Session::SendData(UNIX *u, string data) {
return 0;
};
Session::Session(int rid) {
mtxchanges = { 0 };
mtxchanges = PTHREAD_MUTEX_INITIALIZER;
sessionID = random();
randomID = rid;
changes.clear();
@ -186,7 +190,9 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
// add chenges which need to be send to the clients
//
void Session::ChangeListPush(string chng) {
LockChanges();
changes.push_back(chng);
UnLockChanges();
};
@ -203,13 +209,14 @@ JSONElement Session::ChangeListGet() {
je.name = "changes";
je.value = "[";
LockChanges();
for (iter = changes.begin(); iter != changes.end(); iter++) {
if (iter != changes.begin()) je.value += ",\n ";
else je.value += "\n ";
je.value += (*iter);
}
changes.clear();
UnLockChanges();
je.value += "]";
@ -241,7 +248,7 @@ void Session::AddJSONRailway(JSONParse *jp) {
server->RailwayChange(&r);
jout.Clear();
jout.AddObject("railway", server->RailwayGetJSONRailway(r.x, r.y));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
}
@ -268,7 +275,7 @@ void Session::DelJSONRailway(JSONParse *jp) {
server->RailwayChange(&r);
jout.Clear();
jout.AddObject("railway", server->RailwayGetJSONRailway(r.x, r.y));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
}
@ -292,7 +299,7 @@ void Session::AddJSONInterface(JSONParse *jp) {
server->InterfaceChange(&iface);
jout.Clear();
jout.AddObject("interface", server->InterfaceGetJSON(iface.name));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -318,7 +325,7 @@ void Session::DelJSONInterface(JSONParse *jp) {
jout.Clear();
s = iface.name;
jout.AddObject("interfacedelete", s);
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -342,7 +349,7 @@ void Session::AddJSONSensor(JSONParse *jp) {
server->SensorChange(&se);
jout.Clear();
jout.AddObject("sensor", server->SensorGetJSON(se.name));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -368,7 +375,7 @@ void Session::DelJSONSensor(JSONParse *jp) {
jout.Clear();
s = se.name;
jout.AddObject("sensordelete", s);
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -392,7 +399,7 @@ void Session::AddJSONLocomotive(JSONParse *jp) {
server->LocomotiveChange(&loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco.name));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -434,7 +441,7 @@ void Session::SetJSONLocomotive(JSONParse *jp) {
}
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loconame));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -459,7 +466,7 @@ void Session::DelJSONLocomotive(JSONParse *jp) {
jout.Clear();
s = loco.name;
jout.AddObject("locomotivedelete", s);
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -479,7 +486,7 @@ void Session::SetJSONLocoDest(JSONParse *jp) {
server->LocomotiveSetDest(loco, block, reverse);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
@ -498,7 +505,7 @@ void Session::SetJSONLocoAssign(JSONParse *jp) {
server->LocomotiveSetAssign(loco, block, reverse);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
@ -514,7 +521,7 @@ void Session::SetJSONLocoReset(JSONParse *jp) {
server->LocomotiveReset(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
@ -528,7 +535,7 @@ void Session::SetJSONLocoMan(JSONParse *jp) {
server->LocomotiveSetMan(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
@ -542,7 +549,7 @@ void Session::SetJSONLocoAutoMan(JSONParse *jp) {
server->LocomotiveSetAutoMan(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
@ -556,7 +563,7 @@ void Session::SetJSONLocoAuto(JSONParse *jp) {
server->LocomotiveSetAuto(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
@ -570,7 +577,7 @@ void Session::SetJSONLocoAutoRand(JSONParse *jp) {
server->LocomotiveSetAutoRand(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
@ -594,7 +601,7 @@ void Session::AddJSONTurnout(JSONParse *jp) {
server->TurnoutChange(&to);
jout.Clear();
jout.AddObject("turnout", server->TurnoutGetJSON(to.name));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -620,7 +627,7 @@ void Session::DelJSONTurnout(JSONParse *jp) {
jout.Clear();
s = to.name;
jout.AddObject("turnoutdelete", s);
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -646,7 +653,7 @@ void Session::SetJSONTurnout(JSONParse *jp) {
server->TurnoutSet(name, active);
jout.Clear();
jout.AddObject("turnout", server->TurnoutGetJSON(name));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -670,7 +677,7 @@ void Session::AddJSONBlock(JSONParse *jp) {
server->BlockChange(&bl);
jout.Clear();
jout.AddObject("block", server->BlockGetJSON(bl.name));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -696,7 +703,7 @@ void Session::DelJSONBlock(JSONParse *jp) {
jout.Clear();
s = bl.name;
jout.AddObject("blockdelete", s);
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -712,7 +719,7 @@ void Session::BlockJSONOff(JSONParse *jp) {
jout.Clear();
jout.AddObject("block", server->BlockGetJSON(name));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
@ -727,7 +734,7 @@ void Session::BlockJSONClear(JSONParse *jp) {
jout.Clear();
jout.AddObject("block", server->BlockGetJSON(name));
if (network) network->_ChangeListPushToAll(jout.ToString());
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};

@ -143,6 +143,8 @@ function trackDrawElement(ctx, element, mode) {
ctx.lineWidth = 2;
ctx.setLineDash([0,0]);
ctx.strokeStyle = modcol;
if (element.lockedby && element.lockedby != "")
ctx.strokeStyle = cssVar('--track-color-locked');
trackDrawTrack (ctx, {x: element.x, y: element.y}, element.dir);
}
else if (element.type == RAILWAY_CROSSING) {
@ -151,6 +153,8 @@ function trackDrawElement(ctx, element, mode) {
ctx.lineWidth = 2;
ctx.setLineDash([0,0]);
ctx.strokeStyle = modcol;
if (element.lockedby && element.lockedby != "")
ctx.strokeStyle = cssVar('--track-color-locked');
trackDrawTrack (ctx, {x: element.x, y: element.y}, element.dir);
trackDrawTrack (ctx, {x: element.x, y: element.y}, element.altdir);
}

Loading…
Cancel
Save