sharedについて


投稿ツリー



前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2009/10/4 2:26
SHOO  管理人   投稿数: 658
こんにちは、通りすがり歓迎ですよ。

たしかに、 msg# 1 の最後の呼び出し条件を書いたときにオーバーロードの解決は気になりました。
現状のオーバーロードの解決は、
型が完全に一致している→型をconst型にすると一致する→暗黙変換で型が一致する
の順番で行われるものと認識しており、実際そのようになっているように思います。
おそらく問題なのは「型をconst型にすると一致する」かな?
と、いうわけで、

>「通常型とshared型のメソッドがオーバーロードされている場合に通常型からアクセスすると通常型を優先的に選択する」という規則

は、これを見る限りすでに組み込まれているものかと思います。

私の考えとしては、通常型でマルチスレッドを考慮していない関数から、shared型でマルチスレッドを考慮している関数呼び出したときにおこる問題は、関数の振る舞いにおいては影響がなく、効率の面以外では思いつかないため、通常型のオブジェクトからsharedメンバ関数を呼び出しても問題はないのではないか、という意味でした。
たしかに、効率などを考えるとマルチスレッドを考慮しない場面でマルチスレッドについて処理を行っているものを呼び出すのは、効率の悪いことだと思いますので、そのような非効率な事はさせない、という実装でも悪くはないと思います。
[http://www.kmonos.net/wlog/75.html#_2133070723 もうropeとかしねばいいのに] ←これを思い出した。

何れにせよ、 msg# 1.5.1 で述べた問題がある限り、sharedメンバ関数内ではcastが多用されるコードが予想される気がしますね。
synchronized文内では一時的に型がshared解除されるとか…いや、めっちゃ混乱しそう…
ちなみに、下記のようなコードが問題なのではないかとおもう。
#code(d){{{
import std.stdio;
import core.sync.mutex;

// クラスAはマルチスレッドをまったく考慮していないクラス
class A
{
int count;
// とうぜんfuncに関しても全くマルチスレッドは考慮しない
void func()
{
count++;
writeln(count);
}
}

// マルチスレッドを考慮するクラス。
// 余談だが、すべてのメンバ変数をsharedに対応させるなら shared class B とか
// かけた方がうれしい気もする。
// あと、マルチスレッドを考慮するクラスでは、Mutexを使用するなど、クラスの
// 設計全体に影響がある場合が多いため、一つの関数だけをsharedにする、などは
// 通常難しいのではないかと思うのだが…
class B
{
// 変数aは、マルチスレッドを考慮していないクラスのオブジェクト。
A a;
// 変数aをマルチスレッドのどこからでも触れるように、Mutexを使って保護する
// ことを考える。
Mutex m;
this()
{
m = new Mutex;
a = new A;
}

//--------------------------------------------------------------------------
// ☢Caution!!☢ ☢Caution!!☢ ☢Caution!!☢ ☢Caution!!☢ ☢Caution!!☢
//--------------------------------------------------------------------------
// 問題はこの関数内で起こる。
//--------------------------------------------------------------------------
// ☢Caution!!☢ ☢Caution!!☢ ☢Caution!!☢ ☢Caution!!☢ ☢Caution!!☢
//--------------------------------------------------------------------------
//
// 関数全体を synchronized (this) で覆うような効率の悪い方法ではなく、
// 変数aだけをピンポイントに保護することができるように、shared関数とする
shared void dispCount()
{
// この synchronized 文で、変数aが保護されるため、この内部では
// aをどういじってもマルチスレッドが原因でおかしなことになることはない。
// あと、 m.lock ができないのも問題かと思うが、これは Mutex クラスの
// lock関数/unlock関数のsharedマークで解決か。
// const sharedとかだとどうするべきかも疑問
synchronized (m)
{
// 安全なはずだけど型が shared(A) 型なので、
// sharedメンバ関数ではない A.func 関数は呼び出すことができない
//a.func(); // main.d(56): Error: ...

// したがって、castをしなければいけない
(cast(A)a).func();
}
}
}

void main()
{
auto o = new shared(B);
o.dispCount;
o.dispCount;
o.dispCount;
}
}}}


ちなみに、型システムの利用法をコンパイラの最適化まで話を持っていこうとすると、逆にメモリフェンスを自動で組み込んで最適化によって起こるマルチスレッドのバグを回避してくれたり、アトミック性を保証してくれたりといったことを期待したくなりますね。
投票数:113 平均点:3.81
返信する

このトピックに投稿する

題名
ゲスト名
投稿本文

  条件検索へ


メインメニュー

ログイン

ユーザー名:


パスワード:





パスワード紛失  |新規登録

Menu