diff --git a/lib/api/GwApi.h b/lib/api/GwApi.h index c6d679e..7fdf8cd 100644 --- a/lib/api/GwApi.h +++ b/lib/api/GwApi.h @@ -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: @@ -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 diff --git a/lib/usercode/GwUserCode.cpp b/lib/usercode/GwUserCode.cpp index 7c47a55..f5e9f97 100644 --- a/lib/usercode/GwUserCode.cpp +++ b/lib/usercode/GwUserCode.cpp @@ -46,23 +46,65 @@ class GwUserCapability{ } }; #include "GwUserTasks.h" +class TaskData{ + SemaphoreHandle_t lock; + std::map 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> 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() { @@ -160,12 +202,20 @@ public: else it->second=GwCounter("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; @@ -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){ @@ -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++; } diff --git a/lib/usercode/GwUserCode.h b/lib/usercode/GwUserCode.h index e9b45f5..a0d1019 100644 --- a/lib/usercode/GwUserCode.h +++ b/lib/usercode/GwUserCode.h @@ -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 Capabilities;