ロード トップ 参照元 逆検索 検索 ヘルプ

[logo] バックグラウンドでロードするには


おもいついたこと から分かれてきました。


すごいなこれ

w3m inline image Kterm 版は 、 ここで どんどん 進化している。

240x320 の画面を想定して 40x26 で 使っているんだけど、ちゃんと見れる。

付けているのは こんなオプション

exec kterm-img -geometry 40x26 +sb 
        -fl '-alias-fixed-medium-r-normal--12-*' 
        -flb '-alias-fixed-bold-r-normal--12-*' 
    -e /usr/local/bin/w3m -ppc 6 -ppl 12  $*

こんど、ぞろよしフォントで試そうとしたのだが、vine では なんかうまくいかない。

付けているのは こんなオプション

exec kterm-img -geometry 48x32 +sb 
        -fl '-alias-fixed-medium-r-normal--10-*' 
        -flb '-alias-fixed-bold-r-normal--10-*' 
    -e /usr/local/bin/w3m -ppc 5 -ppl 10  $*

とかやると elisa フォント で みることはできた

仕事場では既に重宝している。小さい画面で Web検索とかして web 見るのに 便利。これが mgterm 壁紙ON で動けば十分なのか..そういう気は まだあまり しない。make していないつうのもあるけど。メモリとか性能とか厳しいから mgl 版に期待はしている。.. ただ機能的にどうよと言われると... kterm 版で マウス使えるし、カシオペアで カーソルキーが使えるようになったから ボタンがあるかどうか... ぐらい?。ボタン付けるとか ...いじる立場だと mgl 版の方がいじりやすいかも知れない。

そろそろこのWikiNameじゃ内容とあわない気もしますが(^^;
で、ktermの方はダウンロードしたプロセスが描画する、という作りなんでしたっけ。 よく覚えてませんが。
となるとMGL的には難しいですね。 現状のロードの仕組みで使えるので、 ktermと同じにするのは諦めます。 ただ、同じようなコードを二人別々に実装するのは無駄も多い気がしますが、 そろそろ機能も出揃ってきたし。--有野

そういえば、カシオペアEXX で、軽いブラウザが手にはいるのならば cgi つかって、ツールつくれば十分じゃんとか書いた覚えがある。
軽いブラウザは手に入ってしまった(or 手に入ったも同然な)わけだから、 それも試してみたいなぁ。cgi のツールって何がいいんだろうか。

それはともかく イメージが 貼れるということは、もっと変なものでも貼れるかも 知れないわけだ。なんか 遊ぶ base として すごいものを手にいれてしまったのかも しれない。



わくわく、早く試したくなってきた。

とりあえず火つけ役らしいです(^^;
こっちの方はまだまだですが、 一応公開してみました。 問題点はたくさんありますが、 一応表示されてて嬉しいです。 ただ、いくつか表示されない事も。 ktermの方のソースが出たら、 いろいろと改善も出来るかもしれませんが、 kterm版が出来たらmgtermと共用、 という路線でもいいかも。
とりあえずこっちは細かい所をつぶしたら、 ボタンとか付けてみようかなぁ、 とか思ってますが、どうなる事やら。--有野

ところで、image のロード中止まるという件。こんな風にしたらどうだろうか。

うーん。このへんでお手伝いできるかも知れない。ちょっと考えてみます。

お願いします。 実はここ、かなりネックです。--有野


なんかこんなかんじかなぁ。作るの難しそう。

process_img のところでは

実際に表示しようとするときに

イメージがキャッシュになければ、

表示すべきページがなくなるときには、

で、実際にイメージをロードするのは、キー入力のところ。


上のをもうちょっと整理。


なんか構想が固まってきました。

モジュール名: bgl --- バックグラウンドローダ。

構想:

バックグラウンドでのロードとキャッシングを このモジュールでサポートする。

ロード機能:

バックグラウンドでのロードをするためには、 callback と ロードする URL, ロードするためのメソッドを登録しなければならない。
また、bgl_proc() という関数を定期的に呼ぶ必要がある。

登録しないといけないものは、次のもの

     ロードオプション
     open_method
     fileno_method
     read_method
     close_method
     callback と  callback を call するときに渡す引数 

ロードオプションで、ptherad() か fork() を使う コンカレントなロードも サポートする。ただし、どちらを使うにしても 面倒な手続きが必要。

fork() を使った場合、fork safe になっている必要がある。 たとえば、atexit() を登録していると... 子プロセスが exit したときに atexit() が動いてしまうとまずい。そのため、bgl が fork した時に呼ぶ関数を 登録する必要がある。また、SIGCHLD を 受け取った場合、 bgl の 関数を呼んで終了ステータスを渡す必要がある。

また、pthread を使う場合は、プログラム全体が thread safe になっている 必要がある。fork 使う場合より面倒かも知れない。

なお、コンカレントなロードをするときも、bgl_proc() は、 定期的に呼ばないといけない。

コンカレントなロードを使わない場合に ファイルディスクリプタを返すfileno_method を登録して、 select を使えるように できる。
( select を使わないと、bgl_proc() が read 待ちでしばしば止まり、 ロード中は レスポンスが低下する。)
ファイルディスクリプタは、select するためにのみ使う。read_method で バッファリングすると 途中で止まるので、実装には注意が必要。
read_method で エラーを返したときに、それまで読んだデータを キャッシュに 保持する ロードのオプションも提供する。 ( これは イメージファイルのヘッダだけ読む ことを想定 )

バックグラウンドでのロードではなく、すぐに ロードするオプションも提供 する。(これもイメージファイルのヘッダだけ読む ことを想定 )

なお、同時にロードする最大数の設定をサポートする。

キャッシュ機能:

キャッシュ機能は、URL に対応する データを得るための メソッドを次のようなインターフェイスで、提供する。

        p = bgl_cache_opne(URL);
             p が NULL なら データなし。
	bgl_cache_read(p,buf,len);
        bgl_cache_close(p);

いまのところ tmpfile() を使って open しっぱなし にしようかと考えている。 ( close するだけで データを消せるため。 )
また、キャッシュデータの容量制限と キャッシュデータの個数制限をサポートする。


なんか、一応形になってきました。

bgl-001.tgz

ステータス:

make ぐらいはできて、なんか良く分からないテストプログラムを動かすことが できます。

USE_FORK を define してやると、(テストプログラムでは) fork しての コンカレントなロードもすることができました。

USE_PTHERAD はゼンゼンだめ。こんな感じで作ろうかなというところ。

SELECT 使うのは 、 うまくいっているみたい。

テストプログラム 以外のテストは、全然できていない。 不安なのは、だれかがロードしているときに、async_read をかけたケース。 とくに、IMMEDIATELY オプションを組み合わせたときの動き。

わかっている問題点としては、少し読んだファイルを 読み込みなおすとき 一旦 サイズが 0 になるタイミングがあること。
これは、サイズが単調に増加するようにしたいと思う。 ( あらたに読んだファイルが 元のサイズを越えたところで 切替える)

ちなみに、テストは popen 使って シェルスクリプトからデータをロードする もの。


w3mmgl とのすり合わせについて。

そんなイメージで考えてます。 ちょっとまだw3mの方がいろいろありすぎるので、まだこのページの内容とのすりあわせの所までは行ってませんが。 とりあえずソースの方のイメージは進んでいるのですが、 このページの成果を今週末に取り込めるかは微妙な所です。--有野

了解です。bgl も テストちゃんとできていないし、足りないメソッドもあるんで、 こちらも ボチボチやります。


再度考えてみる。

作ってみたものの、今の w3m の構造に これを使うのは難しいかも知れない。 ちょっとしかソースみていないが、レンダリングまわりより、 read の メソッドを作ること自体が難しいような気がする。

レンダリングした時点で、w3m 側のページのデータ構造が決まり、イメージ が欲しいということになるはず。ここで、async_read をかけてやればいいと 思う。

で、レンダリングした後に表示ってことになるから、この時点で cache_read を 使ってデータを見る。なかったらしかたがないので無視。 ( 上のところで aync_read をかけずに、ここでかけてもいいかも知れない。)

あとで 完了通知がくるわけだが... 任意のID を 設定できる。 このID が、ページの中の該当イメージを指すようにしてやればいいと思う。

通知が来たときに ページがたまたま表示中なら、イメージを描画してやる。 違うかったら無視。( イメージだけ表示すると、TEXT と重なるようなら、 ページ全体か、表示領域を指定して(それができるならだけど) redraw かけてやってもいいかも知れない。)

あと、ページのデータ構造が消えてなくなった後に通知が来ると困るから、 ページのデータ構造がなくなるタイミングで、キャンセルを発行しとかないと いけないケースがあるはず。( たとえ GC がかってにデータを消すような構造だと まずいんだけども、逆に bgl が ページへのリンクを持っていれば、 read して通知しようとするまで ページデータは消えないはず。 .. だから対応のしようはあると思う。)

ここらへんの処理は問題ないと思うんだけど...。GC に対応しておかない といけないとか、そういうレベルの問題はありそうだけど、 プログラムの構造とは多分関係ないはず。

それより、read method が作れるのかどうか。作ったとして、fork した 子プロセスで動かしても問題ないかどうかの方がネックだと思う。

ポーリング自体は、多少工夫の余地がある。ただ、get_key(-1) したとしても mgl の内部で 100ms ぐらいでポーリングしているんで、get_key(100) としても あんまり変わらないと思う。

なんとなく...コネクションが1本しかないとか そういう構造になっているかも。 そうだとすると、そもそも コネクションを複数作れるようにしないといけない。 そこいらへん、どこみたらいいんだろう。

とりあえずここらへんの事については思う所がいくつかあります。 今週末に現状のから、結構大きく変更する予定です。
コネクションに関してはloadSomethingとかですか?--有野

ちょっと w3m のコードをみて 思ったんですが、どうも w3m 側を open/read/write に分割するところが難しいような 感じがします。

単に file の load だから 大丈夫かと思っていたんだけども。甘かったかも。 ただ w3m 側でループを持たせることができるように するのは 割と簡単。proc(url,handle) という メソッドを定義して、逆に bgl にたいして bgl_xx_write(handle,xxx) と bgl_xx_close(handle) を呼んで もらう API を追加したら、対応が簡単になるかも。

少しbgl.cのmainを読んでみました。 で、実際に使おうとすると、ここに書いてあるように少し組み込みづらいです。
外部のモジュールとするよりも、 すなおにw3mの中の関数使ってthread使って実装する方が楽に思えてきました。 少しthread使っていろいろやってみます。--有野

で、いろいろやってみました。 thread使って、一通り実装して、 一応ちゃんと動いてますが、GCがthread対応してるのが、 winとかLinuxとかSolarisだけで、 しかもちゃんと対応してるのはSolarisだけっぽいので、 NetBSDには使えなさそうです。
こっちのミスかGCのせいかはわかりませんが、 時々まずい動きをします。
ただ、fork使うバージョンに書きかえる時でも、 コードのほとんどはそのまま使えると思うので、 一応アップしておきます。

ここです。

bglのasync_readで作り直す事になりそうです。 file.cのimg_processで使う、asave2tmpを書き直せばよさそう、 とか思ってますが、、、甘いかなぁ。--有野


連絡欄

たぶん見てくれると思うから ここに書いときます。 w3mmgl.tgz で terms.c が ないっす。> 有野さん。

あっ、ほんとだ。了解です。直しました。--有野

受け取りました。ようやく make できました。

いろいろみているんだけども、問題が多々あると 作っている人がいっているのが なんとなくわかりました。それでもイメージを見れるってのは大きい。 嬉しいです。

うーん、今の所ウケはいいですね。 改善の優先順位としてはどんなのがいいですかね?--有野

レイアウトに関して、 具体的な課題が何かってのが 実は良くわかっていないんです。 だから、うまく書けない。それ以外では、w3m のいいところスポイルしちゃダメだと 漠然と思っています。で非同期なロードにこだわっています。本文のロードが 終るまで、オペレーションできないのは我慢するとしても、イメージのロード で止まるのは我慢できない。やっぱり

なるほど。やっぱり現在の、 非同期実現が最重要、という僕の認識でよさそうですね。 使ってみるとやはりあそこが一番目につきますし。
まだサイズ指定が無い時にどうするか、とか悩んでる部分も多いですが、 いろいろやってみます。 Threadでは駄目だ、とかもやってみないと気付かなかったと思うし。
イメージのキャッシュは基本的にはディスク(及びフラッシュメモリ)上にファイルとして保存しているので問題は無いと思いますが?
レンダリングの方は後回しにする予定です。最後までやらないかも。--有野


あ、ここで書いたのは、展開後の イメージデータのことです。 これって容量くうわけですが、もってなくてスクロールのたびに データ展開 するのもなぁ。と 思うわけです。というわけで 1 ページ分ぐらいはもっていて よいのかなぁと。あと、キャッシュデータは file に書くから 沢山使えるという のは幻想かも。 たとえば 私は、/tmp を RAMDISK に しているんで.. メモリと変わることが ありません。RAMDISK 使うのは、flush 自体に 空きがないというのもありますが、 flush を あまり頻繁に書き換えるの 恐いって理由もあります。

日記 みましたが、w3m の方の 非同期化って難しそうですね。

まずは、コピペ->修正でいいんじゃないでしょうか。本体系に影響を与えず 修正できますから.... 最終形も コピペのコードのままっていうのがいいか 、 ちゃんとマージした方がいいかは、やってみてから分かるんじゃないだろうか。

あと、fork での注意としては、fork した子プロセスは、親プロセスに影響を 与えられないから、おもに 子プロセスが使うリソースにのみ注意して やればいいです。そこいらへん共通のコードでちゃんとコントロールするのは 難しいんで、 子プロセスで、動かす コードは独立させた方がちゃんと動くコードを 作るのは楽かなぁなんて思います。

あと、シグナルって、発生元を知ることはできません。また、複数のシグナル が来ても1つに 縮退されてしまう。
で、終了ステータスのみは、wait とか waitpid で 取得することができる。
やっぱり、shell のように fork して1つの仕事をして exit というのが基本だと思います。それが嫌なら プロセス間で通信しないと いけない。で、そういうやりかたする場合、クッキーだとか いろんな状態も 送らなくてはいけなくて、相当たいへんかも。

なるほど。 ではそういう路線でも考えてみます。--有野

hsaka さんの kterm 版 試してみました。なんか PC WATCH とか ZDNET とかが 見れるぐらい レイアウトできています。びっくり。

差と思われるところをチェック。

hsaka さんの kterm 版 キーが入力されたらキャンセルされるようになったみたい。 同期ロードではあるけれども、fork 使って非同期なキャンセルを実現している っていうか。そんなかんじのデザイン。

もう少し工夫加えるとかなり使えるかなぁという気も。 hpcmips みたいな遅いマシンで試したわけではないので、 十分軽くなるかどうかまでは分かりませんが...


(... squid なんか使っている場合だと、 一回リクエストだせばロードが始まってしまうので、 あとで リクエストだせばキャッシュされている。)

という訳でktermの方のレンダリング、真似してみました。 結構違いますね、真面目に作られてました。 まだよく理解してない所とかもあって、妙な挙動する事もありますが、 おおむねよさそうです。ここにおいときます。--有野

日記鯖が落ちてるようなので、 ここに書いておきます。
前回のは、configureスクリプトがバージョン違いでうまくmake出来なかったアーカイブになってしまってました。 今回幅指定が無い時も読み込みを後回しにするバージョンにしたついでにXXMakefileをいれる前のバージョンに戻してしまいました。 後はイメージマップに対応すればkterm版と同じ機能のはずです。
上に書いた場所と同じ所に置いときました。 これでだいぶ実用になりそうです。--有野


インターフェイス: (決めたところまで)

キャッシュ関係


int bgl_cache_status(char *URL);

     URL に対応するキャッシュデータの 状態を返す。

     -1: まったくなし。
     0: データが完全に読み込めている。
     1: 途中まで読み込んで、中断。
     2: だれかが 読み込もうとしている。( が、まだ読んでいない)
     3: だれかが 読み込もうとしていて、read 中。


void * bgl_cache_open(char *URL);

    URL に対応するキャッシュデータがあれば、ハンドラを返す。

bgl_cache_read(void *p, void *buf,int len);   

    キャッシュデータを読み込む。戻り値 read したバイト数。
    0 のとき は EOF。エラーは -1 。

void bgl_cache_close(void *p)

    ハンドラを開放。

int bgl_set_cache_limit(int size, int number);

    キャッシュの 容量/数 の limit を設定。

ロード関係

int bgl_async_read(char * URL,void *arg,struct bgl_async_param *param);

struct bgl_async_param {
        int opt;
        void *(*open)(char *);
        int (*fileno)(void *);
        int (*read)(void *,void *,int);
        void (*close)(void *);
	void (*notice)(void *arg,int status);
};

opt : 

BGL_OPT_CONCURRENTLY  コンカレントな READ を試みる。できない場合は無視。
BGL_OPT_IMMEDIATELY   すぐに: この場合 戻り値は、notice の status 
BGL_OPT_KEEPDATA      エラーになったところまでの データをキャッシュに保持。

callbacks : 

   open --  URL を引数にして、call される。必須。
   fileno --  open したハンドラに対応する ファイルディスクリプタを返す関数。
             オプション

   read -- read メソッド 必須。
   close -- close メソッド必須。

   notice -- 終了したか エラーになったとき call される。
     arg: bgl_async_read の引数の arg と 同一値。
     status:
     -1: エラー
     0: データが完全に読み込めた。
     1: 途中まで読み込んで、中断。

戻り値:
   -1: エラー
  0: キャッシュに データがあった。
  それ以外: リクエスト ID 


int bgl_cancel_async_read(int req_id);

   リクエスト ID に対応する async_read をキャンセル。
   キャンセルした場合、notice コールバックは、呼ばれない。

int bgl_set_async_concurrency(int n);

   read する 並列数を指定。
 

その他

bgl_proc()

     定期的に呼ぶこと。

FORK を使うときのみ必要:

bgl_atfork(void (*func)())

     bgl が、fork した後に呼ぶ 関数を登録。

void bgl_sigchld_handler()

    SIGCHLD ハンドラで 最初に この関数を呼ぶこと。
    waitpid を中で使うので、本来の機能に影響はないはず。

    呼べない場合は... SIGCHLD ハンドラを登録しないこと。

    bgl が exit ステータスを 得られなかったことを検出したら、
    エラーになる。
  


(最終更新 Thu Mar 30 19:18:00 2006)