Skip to content

Commit

Permalink
intermediate: allow to exchange simple data between tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas committed Oct 14, 2023
1 parent 015b476 commit 371372f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 5 deletions.
32 changes: 32 additions & 0 deletions lib/api/GwApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,29 @@ class GwApi{
return format;
}
};
/**
* a simple value container
* to exchange data between tasks
*/
class Value{
long lvalue=0;
String svalue;
bool isString=false;
bool isValid=false;
public:
Value(const String &v){isString=true;svalue=v;isValid=true;}
Value(long l){lvalue=l;isValid=true;}
Value(){}
long getLValue() const{
if(!isString) return lvalue;
return atol(svalue.c_str());
}
String getSValue() const{
if(isString) return svalue;
return String(lvalue);
}
bool valid() const{return isValid;}
};

class Status{
public:
Expand Down Expand Up @@ -133,6 +156,15 @@ class GwApi{
virtual void increment(int idx,const String &name,bool failed=false){}
virtual void reset(int idx){}
virtual void remove(int idx){}

/**
* exchange data between different user tasks
* each task can set arbitrary items
* that can be accessed by other tasks
*/
virtual void setTaskValue(const String &name,const Value &v){}
virtual Value getTaskValue(const String &taskName,const String &name){return Value();}

/**
* not thread safe methods
* accessing boat data must only be executed from within the main thread
Expand Down
58 changes: 54 additions & 4 deletions lib/usercode/GwUserCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,65 @@ class GwUserCapability{
}
};
#include "GwUserTasks.h"
class TaskData{
SemaphoreHandle_t lock;
std::map<String,GwApi::Value> data;
GwLog *logger;
String computeKey(const String &taskName,const String &name) const{
return taskName+":#:"+name;
}
public:
TaskData(GwLog *l){
lock=xSemaphoreCreateMutex();
logger=l;
}
~TaskData(){
vSemaphoreDelete(lock);
}
void setTaskValue(const String &taskName,const String &name,const GwApi::Value &v){
String key=computeKey(taskName,name);
LOG_DEBUG(GwLog::DEBUG,"set task data %s=%s",key.c_str(),v.getSValue().c_str());
GWSYNCHRONIZED(&lock);
data[key]=v;
}
GwApi::Value getTaskValue(const String &taskName,const String &name){
GwApi::Value rt;
String key=computeKey(taskName,name);
{
GWSYNCHRONIZED(&lock);
auto it=data.find(key);
if (it != data.end()) rt=it->second;
}
LOG_DEBUG(GwLog::DEBUG,"get task data %s:%s (valid=%d)",key.c_str(),rt.getSValue().c_str(),(int)rt.valid());
return rt;
}

};
class TaskApi : public GwApiInternal
{
GwApiInternal *api;
GwApiInternal *api=nullptr;
TaskData *taskData=nullptr;
int sourceId;
SemaphoreHandle_t *mainLock;
SemaphoreHandle_t localLock;
std::map<int,GwCounter<String>> counter;
String name;
bool counterUsed=false;
int counterIdx=0;

public:
TaskApi(GwApiInternal *api, int sourceId, SemaphoreHandle_t *mainLock, const String &name)
TaskApi(GwApiInternal *api,
int sourceId,
SemaphoreHandle_t *mainLock,
const String &name,
TaskData *d)
{
this->sourceId = sourceId;
this->api = api;
this->mainLock=mainLock;
this->name=name;
localLock=xSemaphoreCreateMutex();
taskData=d;
}
virtual GwRequestQueue *getQueue()
{
Expand Down Expand Up @@ -160,12 +202,20 @@ class TaskApi : public GwApiInternal
else it->second=GwCounter<String>("count"+name);
return counterIdx;
}
virtual void setTaskValue(const String &name,const Value &v){
taskData->setTaskValue(this->name,name,v);
}
virtual Value getTaskValue(const String &taskName,const String &name){
return taskData->getTaskValue(taskName,name);
}

};

GwUserCode::GwUserCode(GwApiInternal *api,SemaphoreHandle_t *mainLock){
this->logger=api->getLogger();
this->api=api;
this->mainLock=mainLock;
this->taskData=new TaskData(this->logger);
}
void userTaskStart(void *p){
GwUserTask *task=(GwUserTask*)p;
Expand All @@ -179,7 +229,7 @@ void userTaskStart(void *p){
task->api=NULL;
}
void GwUserCode::startAddOnTask(GwApiInternal *api,GwUserTask *task,int sourceId,String name){
task->api=new TaskApi(api,sourceId,mainLock,name);
task->api=new TaskApi(api,sourceId,mainLock,name,taskData);
xTaskCreate(userTaskStart,name.c_str(),task->stackSize,task,3,NULL);
}
void GwUserCode::startUserTasks(int baseId){
Expand All @@ -194,7 +244,7 @@ void GwUserCode::startInitTasks(int baseId){
LOG_DEBUG(GwLog::DEBUG,"starting %d user init tasks",initTasks.size());
for (auto it=initTasks.begin();it != initTasks.end();it++){
LOG_DEBUG(GwLog::LOG,"starting user init task %s with id %d",it->name.c_str(),baseId);
it->api=new TaskApi(api,baseId,mainLock,it->name);
it->api=new TaskApi(api,baseId,mainLock,it->name,taskData);
userTaskStart(&(*it));
baseId++;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/usercode/GwUserCode.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ class GwUserTask{
}
};


class TaskData;
class GwUserCode{
GwLog *logger;
GwApiInternal *api;
SemaphoreHandle_t *mainLock;
TaskData *taskData;
void startAddOnTask(GwApiInternal *api,GwUserTask *task,int sourceId,String name);
public:
typedef std::map<String,String> Capabilities;
Expand Down

0 comments on commit 371372f

Please sign in to comment.