発端はmbedフォーラムのQuestionでこんな質問をもらったことでした。
Is it possible to continue to run the main infinite loop along with the server ?
MiMicのhttpdはHttpd::loop()関数実行しちゃうと、メインタスクを占有しちゃうんだけど何とかならない?ってことでした。自前のプログラムにhttpdを追加するときとか、そういうのがあると便利ですよね。
MiMicはmbed-rtosなので、他にタスクを立ててそっちで実行してもらえば問題ないのですが、めんどくさいのでMiMic::Httpdをバックグラウンド実行するloopTask()関数を追加しました。
使い方は、以下のようにHttpd::loop()の代わりにloopTask()をコールするだけです。なお、この関数は1度実行したら止められません。停止関数は需要があれば作りますので、連絡をください。
この機能はlibMiMic revision 46以降から利用できます。
int main() { Net net; //create a net instance. //try to override setting by local file. cfg.loadFromFile("/local/mimic.cfg"); SimpleHttpd httpd(cfg); //create a httpd instance. net.start(cfg); //httpd.loop(); httpd.loopTask(); //start httpd loop with new task for(;;){ httpd.lock();//prepare to access shared resource counter++; httpd.unlock();//release a lock. Thread::wait(1000); } return 0; }
Sample program
非同期にカウントアップする値をブラウザから観察するサンプルプログラムです。プログラムのポイントは2つあります。
- httpd.loopTask()
httpタスクをバックグラウンドで実行します。2回以上呼び出したりしてはいけません。 - httpd.lock/unlockとconnection.httpdlock/connection.httpdunlock
HTTPDハンドラと外部タスクの間で排他処理をするためのロックオブジェクトです。ロック中はハンドラが停止しますので、外部タスクでのロックは出来るだけ短時間になるようにしてください。
#include "mimic.h" #include "rtos.h" /** * @file * This program is a sample which starts httpd by a subtask. * The value counted up by a main thread is returned by Httpd of a subtask. */ static unsigned int counter=0; LocalFileSystem2 lf("local"); class SimpleHttpd:public MiMic::Httpd { private: ModUrl modurl; //basic URL parser public: SimpleHttpd(NetConfig& i_cfg):Httpd(i_cfg._inst.services.http_port) { } virtual void onRequest(HttpdConnection& i_connection) { char url[32]; int method; unsigned int v; i_connection.lockHttpd(); v=counter; i_connection.unlockHttpd(); //call ModUrl module. if(this->modurl.execute(i_connection,url,32,&method)){ //send 200 OK and requested URL i_connection.sendHeader(200,"text/html",NULL); //show current counter value. i_connection.sendBodyF( "<html><body><h1>Asynchronous test</h1><div>Counter: %u</body></html>",v); return; } return; } }; NetConfig cfg; //create network configulation int main() { Net net; //create a net instance. //try to override setting by local file. cfg.loadFromFile("/local/mimic.cfg"); SimpleHttpd httpd(cfg); //create a httpd instance. net.start(cfg); httpd.loopTask(); //start httpd loop with new task for(;;){ httpd.lock();//prepare to access shared resource counter++; httpd.unlock();//release a lock. Thread::wait(1000); } return 0; }
なお、httpdタスクはメモリ(スタックを含めて300バイト程。スタックは192バイトまで下げられるらしい)とRTOSのスレッドを1つ消費します。