変な人いるし、堅い人もいる。ネタに一生懸命になれる人達がいっぱいいるし、意味なく1行に拘る人もいる。
私はPerlでスーパークリエイター奥一穂(kazuho)さんと会えた。
はせがわさんにも会えた。あ、ちゃうちゃう。はせがわさんはwassrだ。
kazuhoさんにお好み焼き屋で箸袋の裏に貰ったサイン!
今も大事に持ってるお!
次はどのHackerに会えるかな。
はせがわさんにも会えた。あ、ちゃうちゃう。はせがわさんはwassrだ。
kazuhoさんにお好み焼き屋で箸袋の裏に貰ったサイン!
今も大事に持ってるお!
mattn's gntp-send at master - GitHubgntp-sendはコマンドラインプログラムだけど、外部からライブラリとしても使える様にしてあります。
command line program that send to growl using GNTP protocol.
http://github.com/mattn/gntp-send
#include <stdlib.h>
#include <sqlite3ext.h>
#include <growl.h>
SQLITE_EXTENSION_INIT1
static void growl_func(sqlite3_context *context, int argc, sqlite3_value **argv) {
if (argc == 1) {
const char *text = (const char *)sqlite3_value_text(argv[0]);
growl("localhost", "sqlite3", "sqlite3-trigger", "database-update", text, NULL, NULL, NULL);
}
}
__declspec(dllexport) int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api) {
SQLITE_EXTENSION_INIT2(api);
return sqlite3_create_function(db, "growl", 1, SQLITE_UTF8, (void*)db, growl_func, NULL, NULL);
}
こんなコード書いて
# gcc -shared -dll -I c:/sqlite3 -I headers growldb.c lib/libgrowl-static.a -lws2_32 -o growldb.dll
こんな風にコンパイル(Windowsの例)。
sqlite> create table foo(comment text);
sqlite> select load_extension('growldb.dll');
sqlite> create trigger tri_foo
...> before
...> insert on foo
...> begin
...> select growl(new.comment);
...> end;
試してみよう!
sqlite> insert into foo values('hasegawa! xss xss');
xssキター!![]()
use strict;
use warnings;
use Gtk2 '-init', '-threads-init';
use AnyEvent;
use Coro;
use Coro::Timer;
my $window = Gtk2::Window->new('toplevel');
$window->signal_connect(
destroy => sub {
exit;
}
);
my $vbox = Gtk2::VBox->new;
my $button = Gtk2::Button->new('click me');
$button->signal_connect(
clicked => sub {
$button->set_sensitive(0);
async {
Coro::Timer::sleep 3;
Gtk2::Gdk::Threads->enter;
$button->set_sensitive(1);
Gtk2::Gdk::Threads->leave;
};
}
);
$vbox->add($button);
$window->add($vbox);
$window->show_all;
Gtk2->main;
ここでCoro::Timer::sleep
しているのは、生のsleep
を使うとCoroがスケジュール割り当てとして介入出来なくなるのを回避する為。非同期で動作はするものの、スレッド動作になるので「Gtk2::Threads->enter
」と「Gtk2::Threads->leave
」でUIに関連する処理をブロックしなければなりません。つまり例えばボタン押下時の処理が5段階あり、その都度UIの何かしらを変更しなければならない場合、「Gtk2::Threads->enter
」と「Gtk2::Threads->leave
」でそれぞれブロックしなければならない事になります。
button.Clicked(func(w *gtk.GtkWidget, args []unsafe.Pointer) {
button.SetSensitive(false);
if r, _, err := http.Get("http://twitter.com/statuses/public_timeline.json"); err == nil {
// タイムライン取得、表示処理
}
button.SetSensitive(true);
}, nil);
となっていたコードに「go」で実行されるブロックを追加しただけ。
button.Clicked(func(w *gtk.GtkWidget, args []unsafe.Pointer) {
button.SetSensitive(false);
go func() {
if r, _, err := http.Get("http://twitter.com/statuses/public_timeline.json"); err == nil {
// タイムライン取得、表示処理
}
button.SetSensitive(true);
}();
}, nil);
何が言いたいのかというと、groutineはgo組み込みであって、Coroがsleepやhttp_getを置き換えようとしている(CORE::GLOBAL上書きもあるけど)物とは違い、言語として非同期をサポートしているという事。もちろんgoにおいてもボタンクリック時にsleepを呼ぶとUIはブロックされるのだけど、実際sleepなんて使わないし、そもそもgoroutineはスレッドじゃない。A Tutorial for the Go Programming Language実際にはgoが内部でscheduleを行って実行する処理連鎖で実現している。なのでgtkを呼び出す場合においてもgdk_threads_enter/gdk_threads_leaveを呼び出す必要もない。なぜなら並行とは言えど同時実行ではないのでコンテキストスイッチも意識しなくて良い。
Go has its own model of process/threads/light-weight processes/coroutines, so to avoid notational confusion we call concurrently executing computations in Go goroutines.
http://golang.org/doc/go_tutorial.html
go func(){}()
」ブロックだけで非同期処理が書けるという訳。例えばcursesでCUIアプリを書いても画面が崩れる事は無いだろう(未確認)。sub {}
」で匿名関数が使えるがので優秀だが非同期となるとスレッドに頼らざるを得ないのが難点。rubyも同様。pythonは匿名関数が使えないのが少し悲しい(でもpygtkは好きだ)。結局の所、メインループと非同期処理をどう扱うかがネックになっている。例えば各言語でCOMを扱う場合、STA(Single Thread Apartment)しか対応していないCOMは、言語側でメインループをグルグル回すしかない。まぁ言語として用途が違うんだ(JavascriptはそもそもUI記述言語だろ...とか)から、比べちゃならんだろ...とも言えるし。DoEvents
」を実行してプログレスバーを更新するという、なんちゃって非同期処理が横行していた頃だ。最近はVB.NETでコンポーネント自身がスレッドサポート(実際にはデリゲート)しているので簡単に非同期処理が書ける様になったが、これら全てにおいてもやはり非同期対応するつもりの無かったUI処理を、非同期対応にするには多少のコード修正が必要になるには違い無いし、その点でgoには期待している。
このブログを応援する