マルチスレッドプログラミング相談室 その6

このエントリーをはてなブックマークに追加
1デフォルトの名無しさん
マルチスレッドプログラミングについて語るスレ。

その1 http://pc3.2ch.net/tech/kako/997/997345868.html
その2 http://pc5.2ch.net/test/read.cgi/tech/1037636153/
その3 http://pc8.2ch.net/test/read.cgi/tech/1098268137/
その4 http://pc8.2ch.net/test/read.cgi/tech/1130984585/
その5 http://pc11.2ch.net/test/read.cgi/tech/1157814833/

OS・言語・環境は問わないが、それゆえ明記すべし。
テンプレ

【OS】

【言語】

【実行環境】

【その他突起する事項】
2デフォルトの名無しさん:2007/08/13(月) 21:37:27
> 関連スレ
>
> 【マルチコア】並列化について語る【使いこなせ】
> http://pc8.2ch.net/test/read.cgi/tech/1137540671/
>
> pthread地獄 (UNIX板)
> http://pc8.2ch.net/test/read.cgi/unix/1010933537/
>
>
> 関連しやすいので一応
>
> ネットワークプログラミング相談室 Port17
> http://pc8.2ch.net/test/read.cgi/tech/1148944560/l50
>
> 書籍とかはもういいでしょ
コピペ

ちなみに俺はマルチスレッドプログラミングなんてやらない
非ブロッキングとポーリング推奨派だ
3デフォルトの名無しさん:2007/08/14(火) 00:05:04
>>2
最新のスレはこちら

pthread地獄 part 2
http://pc11.2ch.net/test/read.cgi/unix/1166620307/

ネットワークプログラミング相談室 Port20
http://pc11.2ch.net/test/read.cgi/tech/1186418855/
4デフォルトの名無しさん:2007/08/14(火) 14:16:43
2チャンネルもマルチスレッドですね!
5デフォルトの名無しさん:2007/08/14(火) 18:31:20
Symbianケータイで初めて、同期/非同期ってのやったけど、
わけわからんかったなぁ・・・
6デフォルトの名無しさん:2007/08/14(火) 18:40:15
マルチスレッドアプリの設計パターンを学ぶのに良い本orサイトありませんか
できれば対象言語はC++/Posixでおねがいします
7デフォルトの名無しさん:2007/08/14(火) 19:20:17
設計を学ぶのに言語なんか関係ないと思うが。
それとも実装を学びたいの?
8デフォルトの名無しさん:2007/08/14(火) 20:48:20
>>6
Java言語で学ぶデザインパターン入門 マルチスレッド編
結城 浩 (著)

Java並行処理プログラミング ―その「基盤」と「最新API」を究める
Brain Goetz (著), Joshua Bloch (著), Doug Lea (著)

どちらもJavaだけど、現時点でマルチスレッドを学ぶのに
一番適した環境はJavaだと思うので、この辺がオススメ。
C++で使いたいならC++の水準に落とすだけなので損はない。

後者は必ずしも必要ではない情報だと思うけど、
Javaではpthreadより低水準も高水準もカバーできる環境で、
その詳細な内容まで触れられているので参考になると思う。
9デフォルトの名無しさん:2007/08/15(水) 00:43:26
>>7
いや他の言語知らないのでサンプルソースとかが読めないと辛いかなと

>>8
レスありがとう。やっぱりJavaになってしまうのか
本屋で手にとって確認してみます
10デフォルトの名無しさん:2007/08/15(水) 10:44:23
下のやつは、かなりおすすめ。
11デフォルトの名無しさん:2007/08/15(水) 13:24:39
つかさ、やっぱ推薦図書テンプレ化した方がいいんでね?
12デフォルトの名無しさん:2007/08/15(水) 22:10:23
>>6
プログラムデザインのためのパターン言語
ソフトバンク刊
13デフォルトの名無しさん:2007/08/16(木) 00:26:07
ねぇねぇ
メモリブロックとCASの順序ってどうすればいいの?

mb()
CAS()
mb()

って感じでいいの?

あと、マルチスレッドでアルゴリズムが正しいか検証する場合って
みんなどうしてる?長い時間動かして動いてるor正しそうだからオケって
感じ?それともなんかtool使ってるの?
14デフォルトの名無しさん:2007/08/16(木) 01:04:34
競合がおこりそうな状況を作ってぶん回すのはやる
それ以上はどうだろう・・・
15デフォルトの名無しさん:2007/08/16(木) 02:29:15
CASやるときはメモリバリア要らないと思う
でもまぁ環境分からないし、プロセッサのマニュアルを確認してくれとしか

検証はどうするんだろうねぇ・・・
16デフォルトの名無しさん:2007/08/16(木) 03:12:35
>>13
CASの対象にメモリバリアが必要だったら意味がないと思う。
事前の読み込み前に同期させたいなら話は別だが。
17デフォルトの名無しさん:2007/08/16(木) 21:25:12
mutexのロック回数とか計測したいときってみんなどうしてるの?
目視w?
18デフォルトの名無しさん:2007/08/16(木) 21:50:45
なんらかの監視機構を利用する。
19デフォルトの名無しさん:2007/08/16(木) 22:10:02
いまどきのJVMでの競合のないロックって、
CAS2回程度だったりするってどっかで聞いたけど。

ぶっちゃけ下手なことするくらいならロックのがましじゃね?
20デフォルトの名無しさん:2007/08/16(木) 22:17:52
>>19
競合の可能性が高くなければlock freeにするメリットは低い。
ほとんどの場合はロックの方が検証の意味で安全、確実。
21デフォルトの名無しさん:2007/08/16(木) 22:50:57
いまどきのJVMがどのような実装になってるもんなのか知らないけど、
たとえば.NETだと、標準のlockはCASとスピンウェイトでそれでも競合したときだけ
スレッドの切り替えが起こるような実装になってると読んだ。
で競合がない場合はlock取得と開放でCAS2回だと。
これだとlock内での操作が非常に少ない場合、ほとんどlockでいい気がする。
22デフォルトの名無しさん:2007/08/16(木) 22:53:14
ああ、要は、下手にlockフリーにしようとしてCAS操作を何回もやってしまうような実装だと、
何も考えずにlockしたほうがましってことね。
23デフォルトの名無しさん:2007/08/16(木) 23:11:24
吉野家コピペと一緒。
両刃の剣。素人(ry

STMが一般的になれば話は変わってくるんだろうね。
24デフォルトの名無しさん:2007/08/17(金) 07:50:21
            ___
       /      \
クスクスッ /ノ  \   u. \ !?
    / (●)  (●)    \
    |   (__人__)    u.   |
     \ u.` ⌒´      /
         ____
       /      \!??
      /  u   ノ  \    クスクスッ
    /      u (●)  \
    |         (__人__)|
     \    u   .` ⌒/
          ____
       / \  /\  キリッ
.     / (ー)  (ー)\
    /   ⌒(__人__)⌒ \ 
    |      |r┬-|    |  
     \     `ー'´   /
25デフォルトの名無しさん:2007/08/17(金) 21:11:28
using System;
using System.Threading;
public class CyclicBuffer<T> where T : class
{
private static readonly bool s_multiProcsessors = Environment.ProcessorCount > 1;

private volatile int m_head;
private int m_reserve;
private int m_tail;
private readonly T[] m_buffer;

CyclicBuffer(int capacity)
{
m_buffer = new T[capacity + 1];
}

public bool Enqueue(T value)
{
int current;
int next;
do
{
Thread.MemoryBarrier();
current = m_reserve;
next = NextIndex(current);
if (next == m_tail) return false;
} while (Interlocked.CompareExchange(ref m_reserve, next, current) != current);
while (m_head != current || m_buffer[next] != null) Wait();
m_buffer[next] = value;
m_head = next;
return true;
}
26デフォルトの名無しさん:2007/08/17(金) 21:11:58
続き
public T Dequeue()
{
int current;
int next;
do
{
Thread.MemoryBarrier();
current = m_tail;
if (current == m_reserve) return null;
next = NextIndex(current);
} while (Interlocked.CompareExchange(ref m_tail, next, current) != current);
while (m_head < current) Wait();
T value = m_buffer[current];
m_buffer[current] = null;
Thread.MemoryBarrier();
return value;
}

private int NextIndex(int current)
{
return ++current == m_buffer.Length ? 0 : current;
}

private static void Wait()
{
if (s_multiProcsessors) Thread.SpinWait(400);
else Thread.Sleep(0);
}
}
27デフォルトの名無しさん:2007/08/17(金) 21:13:09
ああそうそう、超未検証なのであしからず。
ついでに.NETだが。
28デフォルトの名無しさん:2007/08/17(金) 21:48:14
バグだらけだったよママン
Enqueueは下の間違いわはは
たぶんまだバグだらけだなこれは

public bool Enqueue(T value)
{
int current;
int next;
do
{
Thread.MemoryBarrier();
current = m_reserve;
next = NextIndex(current);
if (next == m_tail) return false;
} while (Interlocked.CompareExchange(ref m_reserve, next, current) != current);
while (m_head != current || m_buffer[current] != null) Wait();
m_buffer[current] = value;
m_head = next;
return true;
}
29デフォルトの名無しさん:2007/08/17(金) 22:03:14
ちょっとおおぼけかましてたので再度
using System;
using System.Threading;

public class CyclicBuffer<T> where T : class
{
private static readonly bool s_multiProcsessors = Environment.ProcessorCount > 1;

private int m_head;
private int m_tail;
private readonly T[] m_buffer;

public CyclicBuffer(int capacity)
{
m_buffer = new T[capacity + 1];
}

public bool Enqueue(T value)
{
int current;
int next;
do
{
Thread.MemoryBarrier();
current = m_head;
next = NextIndex(current);
if (next == m_tail) return false;
} while (Interlocked.CompareExchange(ref m_head, next, current) != current);
while (m_buffer[current] != null) Wait();
m_buffer[current] = value;
return true;
}
30デフォルトの名無しさん:2007/08/17(金) 22:04:00
続き
public T Dequeue()
{
int current;
int next;
do
{
Thread.MemoryBarrier();
current = m_tail;
if (current == m_head) return null;
next = NextIndex(current);
} while (Interlocked.CompareExchange(ref m_tail, next, current) != current);
T value;
while ((value = m_buffer[current]) == null) Wait();
m_buffer[current] = null;
Thread.MemoryBarrier();
return value;
}

private int NextIndex(int current)
{
return ++current == m_buffer.Length ? 0 : current;
}

private static void Wait()
{
if (s_multiProcsessors) Thread.SpinWait(400);
else Thread.Sleep(0);
Thread.MemoryBarrier();
}
}
もうだめかもorz
31デフォルトの名無しさん:2007/08/17(金) 22:16:41
そしてlockと比べて30%かせいぜい40%程度しか変わらんかったw
まあシングルコア、シングルプロセッサの環境だからそもそもまともに試せんがw
32デフォルトの名無しさん:2007/08/17(金) 22:53:59
メモリバリアやめて変数自体volatileにしたら
lockと比べて3〜4倍速くなったバロス。
33デフォルトの名無しさん:2007/08/17(金) 23:16:37
つまらないからどうでもいいんだが
性能比べるなら最低4CPUで
4から128スレッドまで生成してテストしてくれないかな?

34デフォルトの名無しさん:2007/08/17(金) 23:24:10
そんなマシンねーんだよ誰かくれ暮れ。
まあそれを言うなら前すれのjavaのを見てみたいがな。
VMのバージョン依存が大きそうだが
新しい環境ならたぶんsynchronizedのが早いんじゃね?
35デフォルトの名無しさん:2007/08/18(土) 00:34:54
CAS利用したアルゴリズム扱ってる洋書しらん?
和書クソいらん。
36デフォルトの名無しさん:2007/08/18(土) 00:41:12
和書→(excite)→
37デフォルトの名無しさん:2007/08/18(土) 11:21:58
using System;
using System.Threading;

public class CyclicBuffer<T> where T : class
{
private volatile int m_head;
private volatile int m_tail;
private volatile T[] m_buffer;

public CyclicBuffer(int capacity)
{
m_buffer = new T[capacity + 1];
}

public bool Enqueue(T value)
{
if (value == null) throw new ArgumentNullException("value");
int current;
int next;
do
{
current = m_head;
next = current + 1 == m_buffer.Length ? 0 : current + 1;
if (next == m_tail || m_buffer[current] != null) return false;
} while (Interlocked.CompareExchange(ref m_head, next, current) != current);
m_buffer[current] = value;
return true;
}
38デフォルトの名無しさん:2007/08/18(土) 11:22:38

public T Dequeue()
{
int current;
int next;
do
{
current = m_tail;
if (current == m_head || m_buffer[current] == null) return null;
next = current + 1 == m_buffer.Length ? 0 : current + 1;
} while (Interlocked.CompareExchange(ref m_tail, next, current) != current);
T value = m_buffer[current];
m_buffer[current] = null;
return value;
}
}
39デフォルトの名無しさん:2007/08/18(土) 11:47:32
今度こそ最後、汎用化バージョン(structでもOK)
using System;
using System.Threading;

public class CyclicBuffer<T>
{
private volatile int m_head;
private volatile int m_tail;
private readonly Entry[] m_buffer;

public CyclicBuffer(int capacity)
{
m_buffer = new Entry[capacity + 1];
}

public bool Enqueue(T value)
{
if (value == null) throw new ArgumentNullException("value");
int current;
int next;
do
{
current = m_head;
next = current + 1 == m_buffer.Length ? 0 : current + 1;
if (next == m_tail || m_buffer[current].Stored) return false;
} while (Interlocked.CompareExchange(ref m_head, next, current) != current);
m_buffer[current].Value = value;
m_buffer[current].Stored = true;
return true;
}
40デフォルトの名無しさん:2007/08/18(土) 11:48:16
public bool Dequeue(out T value)
{
int current;
int next;
do
{
current = m_tail;
if (current == m_head || !m_buffer[current].Stored)
{
value = default(T);
return false;
}
next = current + 1 == m_buffer.Length ? 0 : current + 1;
} while (Interlocked.CompareExchange(ref m_tail, next, current) != current);
value = m_buffer[current].Value;
m_buffer[current].Value = default(T);
m_buffer[current].Stored = false;
return true;
}

private struct Entry
{
public T Value;
public volatile bool Stored;
}
}

しつこくてすまんのう
41デフォルトの名無しさん:2007/08/18(土) 12:29:09
C#には詳しくないのであれだが,

>public bool Dequeue(out T value)

なんとなく使いにくそう (´・ω・`)
42デフォルトの名無しさん:2007/08/18(土) 13:09:23
うん、使いにくい。
でもintとかの値型が対象のときはこうなってないと対応できないんだよね。
まあ、デフォルト値をパラメータで指定するとかって方法もあるにはあるが。
43デフォルトの名無しさん:2007/08/18(土) 13:14:40
これでCAS操作一回ずつと後はvolatileアクセスだけなので
マルチプロセッサ環境でもうまくスケールするかな…
シングルの環境では、lockよりも4〜5倍程度速い感じ。
44デフォルトの名無しさん:2007/08/18(土) 14:58:22
ネタにマジレスするのはどうかと思うが
これ整合性とれてねーじゃんw
不完全だろw
45デフォルトの名無しさん:2007/08/18(土) 15:02:59
整合性ってなあに…?(´・ω・`)
46デフォルトの名無しさん:2007/08/18(土) 16:35:10
不完全ってなあに…?(´・ω・`)
47デフォルトの名無しさん:2007/08/18(土) 17:22:59
マジネタにネタレスしたんだろ
48デフォルトの名無しさん:2007/08/18(土) 17:57:25
こういうの微妙に不思議なんだけど、
シングルプロセッサ環境でも複数スレッドの方が速くなるのな。
なんでだろ?.NET環境特有の現象?

1スレッドと10スレッドでトータルの実行時間は3倍くらいにしかならない。
100スレッドだとせいぜい20倍くらい、つまり5倍くらいスループットが上がる。
49デフォルトの名無しさん:2007/08/18(土) 18:05:22
それどんなプログラム?
50デフォルトの名無しさん:2007/08/18(土) 18:20:44
上のやつとか。
CPU(とメモリ)依存処理ばかりなのになんでだろう。
51デフォルトの名無しさん:2007/08/18(土) 18:43:55
ソースアップしてくれんとわからんね。起動やJITにかかってる時間も含んでる?
52デフォルトの名無しさん:2007/08/18(土) 19:00:11
計測は、できるだけ実際の実行部分だけになるように
一応注意してやってはいるんだけどねぇ。

今外なのでソースは出せんが、ゲートとカウントダウンラッチ使って
間の時間を計測してる。計測精度は問題ないものを使ってる。StopWatchね。

ラッチは自作だけど、100万回ループの最初と最後だから
実装がいまいちでもまあそれほど大きな影響はないはず。

スレッドが多いほど処理スレッドに割り当てられるCPU時間が
ある程度は増えるかも知れないが、5倍てのはそういう問題の範囲じゃないと思うんだよね。
53デフォルトの名無しさん:2007/08/18(土) 19:06:12
>>39-40
物凄くレアなケースだが、いわゆるABA問題にハマる可能性があるよね。

キューが空のときに、Enqueue()の
> if (next == m_tail || m_buffer[current].Stored) return false;
の行の実行が終わった直後にコンテキストスイッチが入るなどして、次の
> } while (Interlocked.CompareExchange(ref m_head, next, current) != current);
が実行されるまでの間に別スレッドがcapacity + 1回のEnqueue()と1回のDequeue()を行ったとすると、
キューが満杯なのにCompareExchangeが成功してしまう。

同じことはDequeue()側でも起こりうるね。(キューが満杯のとき、Dequeue()内のif文と
CompareExchangeの間で別スレッドがcapacity + 1回のDequeue()と1回のEnqueue()を行った場合とか)

こういう問題への対策法としては、capacityを十分大きくしておくくらいしか
思いつかないけど……
54デフォルトの名無しさん:2007/08/18(土) 19:08:40
windowsアプリでやってるので、後でコンソールでも試してみよう。
あとは、スレッド1このときにメインスレッドで直接実行してどうなるか、かな。
55デフォルトの名無しさん:2007/08/18(土) 19:12:59
>>53
なるほど、ちゃんと考えてないけど確かになりそうだ。
やっぱ更新バージョンが必要になるのかなぁ…
56デフォルトの名無しさん:2007/08/18(土) 19:24:54
いや、更新バージョンじゃだめだな。
インデックスの扱いを工夫、かな。
57デフォルトの名無しさん:2007/08/18(土) 20:01:55
つーかみんな論文とか読んで先人はどう工夫した
かぐらい考えてからソースコードかけよなぁ

58デフォルトの名無しさん:2007/08/18(土) 23:11:48
Advanced Windows
ttp://www.amazon.co.jp/Advanced-Windows-改訂第4版-ジェフリー-リッチャー/dp/4756138055

この本、よんだことある人いる?
C,C++でマルチスレッド組むのに有用な本なんだそうなんだが、いかんせん値段が・・・
59デフォルトの名無しさん:2007/08/18(土) 23:19:18
>>53
変数は配列長の整数倍でできるだけ長い周期でループするようにして、
インデックス使用時に配列長で剰余をとるようにしたら、結構遅くなったw

インデックスで必要なビット長を求めて、残りの上位ビットを
サイクル数のカウンタとして使用するようにしたらだいぶ速くなった。
前のよりは1割程度遅くなったが、ここらでいっぱいいっぱいかな。
60デフォルトの名無しさん:2007/08/18(土) 23:22:14
>>59
そんな申し訳ないことして実際どれぐらい役に立つのw
オナニーバイナリ生成ぐらいがいいとこだよね?
61デフォルトの名無しさん:2007/08/18(土) 23:24:52
日本語でOK
お前さんは役に立たないことは一切やらないのかね?
62デフォルトの名無しさん:2007/08/18(土) 23:26:20
まあいろんなものを実装する練習になるから
まったく役に立たないわけでもないんだけどな。
63デフォルトの名無しさん:2007/08/18(土) 23:29:52
>>62
中途半端にかじった奴が糞コード晒すのとどうか思うのだが?
使えるならまだしも危険すぎだろwこんな糞コードしかかけないんだから
止めろよ。ゆとり夏房は本当に困る
64デフォルトの名無しさん:2007/08/18(土) 23:33:46
どしたん?
65デフォルトの名無しさん:2007/08/18(土) 23:37:30
>>63
「これこれの理由で危険だから使わないように」とでもコメントすれば済むことではないかと。
66デフォルトの名無しさん:2007/08/18(土) 23:41:35
糞なとこを指摘してやれば役にも立つのに。

>使えるならまだしも危険すぎだろw
いや誰も実際に使おうなんてやつはいないだろw
67デフォルトの名無しさん:2007/08/18(土) 23:45:42
>>66
こういうものは指摘しても理解できないだろ?
俺はこんなコード書くやつがまともな姿をした
人間だとはとても思えないんだよ。
68デフォルトの名無しさん:2007/08/18(土) 23:52:36
>>59
ていうか配列長を2の冪乗に切り上げておけば、
ビットマスクとのAND演算だけで済むでしょ。
69デフォルトの名無しさん:2007/08/19(日) 00:01:21
それは思ったが、無駄が多かったのと、キャパとの兼ね合いで
空もしくは一杯の判定が微妙にややこしくなりそうなのでやめた。
でも確かにサイクルカウントを上位ビットに持つよりはずっと単純だったかも試練。
7068:2007/08/19(日) 00:10:34
>>69
いや、capacityも配列長に合わせて切り上げちゃっていいんじゃない?
どうせパフォーマンス重視なんだから、capacityなんて厳密に扱う必要はないと思うが。
71デフォルトの名無しさん:2007/08/19(日) 00:21:34
うーん、容量固定のキューだったからね、今回はこれは変えたらだめかなって勝手に。
まあ、実際にこんなものを作ることがあったらそうすると思う。
72デフォルトの名無しさん:2007/08/19(日) 05:21:55
>>67
>こういうものは指摘しても理解できないだろ?

ここは相談室なんだから、相談相手になる気がないなら他へどうぞ
73デフォルトの名無しさん:2007/08/19(日) 09:11:12
>>58
マルチスレッドに限らず、Windowsプログラミング全般においてその本は
とても有用なので、買って損はないよ。

ただし、各種オブジェクト単体での深い説明が中心で、スレッドの作法だとか
そんな話は皆無で、マルチスレッドの入門書として期待しているなら
やめた方がいい。

例えば、クリティカルセクションが他の同期オブジェクトよりも軽いという点について、
OS内部でどう実装されているのかという話が書いてある。

マルチスレッドの話が読みたいなら「Win32マルチスレッドプログラミング」の方が
いいと思う。(俺は見たことないが)
74デフォルトの名無しさん:2007/08/19(日) 19:00:00
>>67なにまともなフリをしてんだおまえはw
75デフォルトの名無しさん:2007/08/19(日) 19:04:25
でどの辺が糞コードでどの辺が中途半端にかじったぽいのか早く教えて
76デフォルトの名無しさん:2007/08/20(月) 14:15:47
この絡み方厨房の典型だなw
77デフォルトの名無しさん:2007/08/20(月) 14:18:42
そうやってすぐ厨房扱いする奴も大して変わらん
78デフォルトの名無しさん:2007/08/20(月) 16:45:02
厨房に厨房が返してるだけだろ
79デフォルトの名無しさん:2007/08/22(水) 22:21:13
mutexが永田ロックかけてるのか
まだロックかけないで痛めつけてるのか
計測するほうほうないですか?

pthreadでお願いします。
80デフォルトの名無しさん:2007/08/26(日) 21:42:55
C言語歴15年とかいう人が
ローカルにコピーすれば以下のような
コードがOKだと主張するのですが本当なのw?


struct data{
int len;
char buf[128];
}
struct data[6];
int index;
これをグローバルで定義しておいて

void *thread_1(void *arg){
data[index];
//データ書き込み処理
 index++;
}

void *thread_2(void *arg){
int l_index = index;
//データ読み込み処理
}

絶対 indexをローカル変数に代入して
順番考慮してないから2回処理しそうな
気がするんだけどさー
なんかこんな人のプログラム見るのやだ
逃げたいタスケテ


81デフォルトの名無しさん:2007/08/26(日) 21:48:16
>>80
実はスレッドでなくファイバだったとか。
82デフォルトの名無しさん:2007/08/26(日) 21:50:26
HPの鯖でpthread使って書いてますけど
ファイバってことはありえないですよねw?

まじ釣りとかじゃなくて本気でこんなコード生成
するんですよ。困ってる
83デフォルトの名無しさん:2007/08/26(日) 21:53:21
>>80
オマエの日本語やコードの貼り方も相当なもんだ。困ってる
84デフォルトの名無しさん:2007/08/26(日) 21:53:47
ごめん許してくれ
85デフォルトの名無しさん:2007/08/26(日) 21:55:27
マ板向けの話題かな
86デフォルトの名無しさん:2007/08/26(日) 21:56:49
これって絶対ネタだよな
馬鹿でも考えりゃ排他必要な事解かると
87デフォルトの名無しさん:2007/08/26(日) 22:03:55
満を持してvolatileの登場だな
88デフォルトの名無しさん:2007/08/26(日) 22:06:04
>>87
それもネタだろw
89デフォルトの名無しさん:2007/08/26(日) 22:51:08
>>80悪いがそのコードの意味がわからなくてなんとも胃炎。
90デフォルトの名無しさん:2007/08/26(日) 23:06:45
>>89
文脈から想像して、
int l_index = index;
このようにindexをローカル変数にコピーしてから、そのコピーを使って
配列参照すればロックとかいらない、とC言語歴15年さんが主張している。
と読んだ。

ただ、コードは明らかに抜粋なので、状況によってはOKなのかも知れない可能性はある。

thread_1がデータの更新処理で、thread_2は現在の最新データを取得するだけ、
配列は十分に大きく、データの空チェックは別にあるとか。
あるいは、thread_1とthread_2でキューを実現しようとしているなら問題だけど、その場合も
コードが断片すぎるので、前後の記述によっては問題ないかもしれず。

それを含めて>>80が明らかな問題であることを認識した上で書き込んでいるなら、
最初からマ板に行くべきかと。
91デフォルトの名無しさん:2007/08/26(日) 23:14:21
>>90

SMPなんかでCPU入れ替わったら
問題おきないかなぁ?

92デフォルトの名無しさん:2007/08/26(日) 23:22:06
>>90
キューなどの順序性保証が必要なものだとあきからにやばいけど、
掲示板などに書き込まれたデータの最新の1レコードを定期的に
表示更新っていうパターン(厳密な意味での最新版にはこだわらないもの)
なら、volatileのレベルで妥協できる場合もあるんじゃないかって
思ったんだけど。
thread_2の例が現状のindexをいじらずに現時点のindexのレコード参照
しているだけみたいだから。
93デフォルトの名無しさん:2007/08/26(日) 23:26:28
絶対2回読む可能性捨てきれないし
こんな実装商用レベルでしないよなぁ
きっとどっかの研究室だろうなぁ。
教授が書いたコードだから絶対だみたいな感じなんだろうなぁ
94デフォルトの名無しさん:2007/08/27(月) 11:03:22
それならまさに発見的手法だな
95デフォルトの名無しさん:2007/08/28(火) 22:57:45
【OS】 WinXP SP2
【言語】 VC8
【実行環境】 2000以降、可能であれば9x以降
【その他突起する事項】 C++ソースコード上での解決が望ましい

TerminateThreadだと、終了させたいスレッドのハンドルがあればスレッドを終わらせる事ができますが、
これは基本的に最終手段としてスレッドを終わらせる為の物で、初期のスタック割り当てを解除する機会がなかったり、色々問題があるようです。
なので、スレッド外部からExitThreadの様にスレッドを終わらせるにはどうすればいいんでしょうか。
対象のスレッド内で、終了される"かもしれない"タイミングは把握可能です。
96デフォルトの名無しさん:2007/08/28(火) 23:10:34
終了フラグを用意して、スレッドが終わって欲しくなったらフラグを立てる。
対象スレッド内で、今だったら別に終了してやってもいいというタイミングで、フラグをチェックして自主的に終了する。

フラグの読み書きは、ちゃんとクリティカルセクションやミューテックスで囲むか、インターロック関数を使うか、メモリバリアを張ること。
97デフォルトの名無しさん:2007/08/28(火) 23:11:47
・終われフラグなりイベントなりを用意
・要所要所でフラグ/イベントをチェックしてオレオレ例外をthrow
・スレッドの開始点でtry〜catch

でとりあえずできる
他のやり方でも結局こうなると思う

コールスタックにC関数が挟まるとダメな場合もあるので注意
98.95:2007/08/28(火) 23:18:11
Sleepしてる間に終わらせるフラグが立つので、待ち時間が長いです...
99デフォルトの名無しさん:2007/08/28(火) 23:25:03
>>95
メッセージなり何なりを対象スレッドに投げて、対象スレッドに自ら涅槃の道に旅立ってもらう。
100デフォルトの名無しさん:2007/08/28(火) 23:44:30
>>98
Sleepを細かく分ければいい。
for (int i=0; i < 10; ++i) {
Sleep(100);
check_exit_flag();
}
こういうポーリングがいやならEventつかって待機関数で待つとか
101デフォルトの名無しさん:2007/08/29(水) 08:59:33
【OS】 Xp sp2

【言語】 VBA

【実行環境】 Q6600

VBAってマルチスレッドできないともできるとも明記されていないんです。
質問なんですが、VBAにかかわらずマルチスレッド化によって、『比較的発生しやすい障害』というのは何でしょうか?

C等ならPUSH、POP等のメモリ操作がいちばん気をつかいそうなところですよね。
VBAでは、適所に Do Eventを2つ入れること(実験により1つではエラー起きやすい)、変数のグローバル宣言にきをつけること(2つのスレッドで同じ変数を呼ばない)ことくらいですかね。プロシージャーは同時に使っても今のところ問題ありません。

どうぞよろしくお願いします。
102デフォルトの名無しさん:2007/08/29(水) 10:07:45
>【言語】 VBA
>VBAにかかわらず

どっちだよ
103デフォルトの名無しさん:2007/08/29(水) 10:54:17
>マルチスレッド化によって、『比較的発生しやすい障害』
>101のような香具師が手を出してプロジェクトを台無しにする可能性が高まること。
104デフォルトの名無しさん:2007/08/29(水) 10:55:09
日本語でおk
105デフォルトの名無しさん:2007/08/29(水) 11:36:22
> VBAってマルチスレッドできないともできるとも明記されていないんです。

M$に問い合わせろよ
106デフォルトの名無しさん:2007/08/29(水) 12:51:30
煽る人ばっかりで、本日はまともな人いないんですねー。><

失礼しました!
107デフォルトの名無しさん:2007/08/29(水) 22:41:29
>C等ならPUSH、POP等のメモリ操作がいちばん気をつかいそうなところですよね。
お前はいったい何を言っている?
108デフォルトの名無しさん:2007/08/29(水) 22:47:28
>>101
お前の居場所はこっちだ
http://pc11.2ch.net/test/read.cgi/tech/1178723829/
109デフォルトの名無しさん:2007/08/29(水) 22:50:49
Cカップの子を触るのにおもいっきり触るのか
それともソフトタッチでいくのかこれは結構気を使うって
ことなんだな
110デフォルトの名無しさん:2007/08/29(水) 22:58:17
PUSH,POPは気を使わない。それぞれ単純に排他制御するだけだ。
気を使うのは、例えば何かの目的のために一つの処理の中で
pop,pushを続けて行おうとたらその間に別スレッドが実行されて
意図せず状態が変わってしまうようなことが発生すること。
排他制御していない箇所はどんなタイミングでどのスレッドが
実行されるかわからないことを肝に銘じておく必要がある。

『実験により1つではエラー起きやすい』
こんなこと言ってるようじゃ駄目だ。なぜ1つでエラーと
なったのか論理的に分かるまで追え。まあDoEventを愛用
する奴にはマルチスレッドは剥いていない
111デフォルトの名無しさん:2007/08/29(水) 23:15:46
VBAってCOMオブジェクト主体じゃないのか
マルチスレッドの意味あんのかな
112デフォルトの名無しさん:2007/08/30(木) 00:43:06
>101
VBA単独でスレッドを起こす手段がないからな。明記する必要もないだろ。
VBAだけじゃMutexとか同期用のオブジェクトをどうやって扱ったらいいものか、
スレッドを起こす手段がないので同期に関する記述もないからなぁ。
それにCOMだし意味がないかもな。
113デフォルトの名無しさん:2007/09/08(土) 01:29:00
適当なスレが判断できないのでここで質問させて下さい。
msvcrt.dllやスタティックなVC6以降のmallocとfreeの動作についてですが、
_beginthreadexで作成した各スレッドで、あるスレッドがmallocしたメモリを
違うスレッドでfreeする事は合法でしょうか?
過去の自分の書いたコードで見つけてしまいました。
なんかやばそうな気はするんですが。
114デフォルトの名無しさん:2007/09/08(土) 01:35:12
>>113
何を知りたいの?もうちょっと明確に話まとめろよ
このインキン野郎が
115デフォルトの名無しさん:2007/09/08(土) 01:51:13
>>113
スレッドが異なることは問題ない。

メモリ管理で問題になるのはモジュール(EXEやDLL)が異なる場合。
ただし、この場合でもすべてのモジュールのCランタイムを
動的リンク(msvcrXX.dllを使う)にしておけば、問題は発生しないはず。
116デフォルトの名無しさん:2007/09/08(土) 21:25:21
ありがとうございました。
一応きちんと動いてはいるみたいなので放置します。
117デフォルトの名無しさん:2007/09/08(土) 23:20:00
マルチスレっ
118デフォルトの名無しさん:2007/09/09(日) 03:22:50
合法か違法かで言えば合法だろうし、(問題でてないのに)直すってのもアレだけど、
行儀わるいよな。
119デフォルトの名無しさん:2007/09/09(日) 03:47:08
>>118
アプリ全体のログを採る処理で、printfみたいな書式文字列を
mallocやreallocでメモリに貯めていって、ある程度溜まった段階で
清書してファイルに吐き出して、使った分をfreeしてくという仕組みなんですが、
CriticalSectionの排他で順番だけ決めてるだけで、どのスレッドが
メモリ管理をする、というのを決めてないんです。
まあ、最初と最後の破棄とかはメインスレッドがするんですが。
試しにスレッド間通信したらパフォーマンスが悪かったので
こんな仕様にしたような記憶があります。
どうしたらいいでしょうかね。
120デフォルトの名無しさん:2007/09/09(日) 11:39:09
きちんと管理できてるんなら問題ないでしょ。
C++ならstd::stringとか使ってくれた方が楽そうだけど
121デフォルトの名無しさん:2007/09/09(日) 15:29:38
マニアックにboost ropeで
122デフォルトの名無しさん:2007/09/10(月) 07:56:13
boost? STLportじゃなくて?
123デフォルトの名無しさん:2007/09/16(日) 18:00:27
XP/2000のスレッドで質問です。
親子関係にあるスレッドで、親をなるべくブロックさせずに、
毎秒数KB程度のデータを子に送信したいと考えています。
(子は1つで、子の応答はいくら遅れてもかまわない)
クリティカルセクションでデータの排他をに試したら、
子供の処理が長引くだけ親がブロックされてしまうので、
別の方法を検討しています。
こういった場合、スレッド同士の同期オブジェクトを介さずに
データをバッファに溜めておける名前付きパイプが良いかなと
思ったのですが、こういった用途に使えるでしょうか。
124デフォルトの名無しさん:2007/09/16(日) 18:16:31
パイプの長さは必ず確保するという話ではなかった気がするなあ

>クリティカルセクションでデータの排他をに試したら、
>子供の処理が長引くだけ親がブロックされてしまうので

通常、

バッファへの追加
バッファからの取り出し

以外は排他する必要はないと思うんだが、違うのか?
125デフォルトの名無しさん:2007/09/16(日) 18:25:19
>>123
子スレッドが処理終わるまでロックさせっぱなしにしないで、
さっさと必要なデータをコピーしてクリティカルセクションから抜けたら?
126デフォルトの名無しさん:2007/09/16(日) 18:38:07
>>123
子供2つにすればいいだろボケシネカス
127デフォルトの名無しさん:2007/09/17(月) 00:55:31
10ヶ月かかるし。
128デフォルトの名無しさん:2007/09/18(火) 20:48:36
処理が終わるまで待ってたらスレッドの意味が無い。
129デフォルトの名無しさん:2007/09/19(水) 20:55:43
【OS】
Debian Etch Linux kernel 2.6.18
【言語】
C pthread
【実行環境】
GNU gdb 6.4.90-debian

gdbでのマルチスレッドのデバッグ中、任意のスレッドでステップ実行をしていると
とつぜんカレントスレッドが切り替わり、
ステップ実行していたスレッドの実行位置が失われる現象に遭遇します。
デバッグ対象のプログラムは、動作確認がとれているオープンソースのプログラムです。
原因、回避法等ご存知のかた、ご教示いただけないでしょうか
130デフォルトの名無しさん:2007/09/19(水) 21:12:16
gccスレにも行っとけ
131デフォルトの名無しさん:2007/09/19(水) 22:58:11
>>129
250万でサポートしてやるけどどうよ?
132デフォルトの名無しさん:2007/09/20(木) 23:06:29
250万の内訳を教えてくダサイ
133デフォルトの名無しさん:2007/09/20(木) 23:24:38
サンドバック料:200万
治療代:50万
134デフォルトの名無しさん:2007/09/20(木) 23:28:49
>>132
年間保守契約費 200万
登録費       30万
事務手数料 20万

だが?
135デフォルトの名無しさん:2007/09/21(金) 23:17:41
ずいぶんと安いね
136デフォルトの名無しさん:2007/09/23(日) 04:16:06
これからはsignalfdだな
137デフォルトの名無しさん:2007/09/24(月) 14:05:07
ロックしたら負けかな、と思ってる
138デフォルトの名無しさん:2007/09/24(月) 18:56:19
erlangマンセー
139デフォルトの名無しさん:2007/09/29(土) 12:41:04
malloc(), free()ってスレッドセーフなんですか?
140デフォルトの名無しさん:2007/09/29(土) 15:01:14
お前が使っているライブラリのマニュアル嫁
141デフォルトの名無しさん:2007/09/29(土) 18:07:16
>>140
man malloc
ってやってもスレッドセーフに関する記述がないんです...
142デフォルトの名無しさん:2007/09/29(土) 18:41:26
使っているOSの名前、バージョンを言わないのは初心者気取りか?
143デフォルトの名無しさん:2007/09/29(土) 20:23:28
対応してる。大丈夫だ。
144デフォルトの名無しさん:2007/09/29(土) 22:14:38
>>143
安心しました。ありがとうございます。
145デフォルトの名無しさん:2007/09/29(土) 23:24:04
藻前詐欺にあい易いタイプだろ
146デフォルトの名無しさん:2007/09/29(土) 23:39:03
ワロタ
147デフォルトの名無しさん:2007/09/30(日) 01:06:02
昔おれ衝動買いの時によくやった
店員に騙されるパターン
信じてたのに・・・・
148デフォルトの名無しさん:2007/09/30(日) 01:20:45
マルチスレッドでcoutを使うと表示がぐちょぐちょになって醜いです。
どうしたらいいでしょうか?
149デフォルトの名無しさん:2007/09/30(日) 01:21:34
C++の仕様。
printf使いなさい。
150デフォルトの名無しさん:2007/09/30(日) 01:27:17
すみませんprintfでも同じです
151デフォルトの名無しさん:2007/09/30(日) 01:31:42
coutという一つの資源を複数のスレッドで取り合うからそうなる。
排他機構を使ってひとつのスレッドが使っているときに他のスレッドが使うことが無いようにしろ。
152デフォルトの名無しさん:2007/09/30(日) 01:33:10
出力スレッドでも作って、そいつに全部押しつけろ。
153デフォルトの名無しさん:2007/09/30(日) 10:08:32
pthreadつかってマルチスレッドのプログラム作ってるんだけど.
なぜか特定のタイミングでピタッと動かなくなる(デッドロックというのか?)
それ以降プログラムがうんともすんともいわなくなる.

デバッグする際にみんなどういうことやってる?gdbは使い物にならないし...ltraceも使えない...
やっぱりソースコードを目で追っていってるわけ?
154148:2007/09/30(日) 10:48:06
>>151-152
そんな事したらめんどくさくないですか?
もうちょっと簡単な方法でお願いします
155デフォルトの名無しさん:2007/09/30(日) 10:56:45
>>154
諦めろ
156デフォルトの名無しさん:2007/09/30(日) 10:58:21
ソースを追うっていうか、どんなケースが起こりえて、
すべてのケースの組み合わせに対応できているか検証する。

大体は、止まりそうな場所はわかるから、そこを調べて、
次に、ブロックするかもしれない操作を洗い出して調べる。
止まる場所は突き止めたけど、どうして止まってしまうかわからない場合は、
状態をログに出したりするかな。

デッドロックより、最適化とかOoOでの実行順序の入れ替わりとか、
可視性が関わるバグの方が、調べるの大変だと思う。
157デフォルトの名無しさん:2007/09/30(日) 11:12:22
coutやprintfがMT-safeでも、
出力が崩れるのはどうにもならないと思うので、
出力処理全体を1セットとして、ちゃんと排他しないと駄目だろう。
158デフォルトの名無しさん:2007/09/30(日) 12:22:06
>>148
スレッドごとに出力先を分ける。
159デフォルトの名無しさん:2007/09/30(日) 13:23:05
>>154
マルチスレッドプログラミングが「面倒くさい」ものでないならば
そもそもこんなスレは存在して無いだろうよ。
160デフォルトの名無しさん:2007/09/30(日) 13:40:06
>>154
ぐちょぐちょにならないっていうことの意味をもっとはっきりしないとだめだね
一番綺麗なのは、スレッドAの表示がすべて終わってからスレッドBの表示をすることだが、それならシングルスレッドにするのが一番簡単
つまりマルチスレッドやめれば解決
161デフォルトの名無しさん:2007/09/30(日) 13:43:19
>>154
ドトネトのSystem.Consoleクラスならマルチスレッドセーフ。w
162デフォルトの名無しさん:2007/09/30(日) 13:50:16
>>161
素朴な疑問なんだが、そのマルチスレッドセーフとは出力が混ざらないことまで保障してくれるのかね。
# だとしたら、逆に激しく不便なんだが。
163デフォルトの名無しさん:2007/09/30(日) 14:03:37
>>158のは、言われてみれば当たり前なんだが、
簡単だし、間違いないな。

変数/オブジェクトの持ち回りとかが、複雑になってたら、
スレッドローカルな変数を使えばいいし。
164デフォルトの名無しさん:2007/09/30(日) 14:04:48
メソッド一発分が安全に動くだけだろ。
165デフォルトの名無しさん:2007/09/30(日) 14:07:48
>>162
Console.WriteLineはアトミックに実行されて出力は混ざらないね。
ReadLineは1つのスレッドが入力実行中は他はブロックされるかな?

混ざらないとどの辺りが激しく不便なのでしょうか?
166デフォルトの名無しさん:2007/09/30(日) 14:09:34
>>164
それ以外に何を求めると?
167デフォルトの名無しさん:2007/09/30(日) 14:12:41
行単位でも混ざって欲しくなかったら>164では不十分だろ。
行単位で適宜出力して欲しかったら混ざらなかったら不便だろ。
168デフォルトの名無しさん:2007/09/30(日) 14:15:25
まず、「混ざる」の定義からはじめろ。
バイト単位なのか、
マルチバイト、ワイドキャラクタ等の文字単位なのか、
出力ストリームのメソッド単位なのか、
複数の出力ストリーム書き込みをまとめた、プログラムの中で定めたオレ単位なのか。
169デフォルトの名無しさん:2007/09/30(日) 14:19:52
初心者なオレのためにライブラリ、クラスのスレッドセーフの
定義を騙ってください。
170デフォルトの名無しさん:2007/09/30(日) 14:28:21
>>166
何も求めてねーよ。
>>162に答えただけだ。

171デフォルトの名無しさん:2007/09/30(日) 14:34:16
>>170
メソッド一発分が安全に動くだけ以外のことをされると
マルチスレッドでは激しく使い辛いですな。。
172デフォルトの名無しさん:2007/09/30(日) 17:35:19
>マルチスレッドでは激しく使い辛いですな。
わかんねー奴に俺が翻訳してやる。
せっかく並列に動くのに余計なロックするなや
別に使い方が面倒になるわけじゃないよ
いじょ
173148:2007/09/30(日) 18:12:10
もういいです。わたしが馬鹿でした
もうあきらめます。
174デフォルトの名無しさん:2007/09/30(日) 18:20:52
なんだ、学習意欲のないやつだな
175148:2007/09/30(日) 19:21:43
すみませんが、本当にわかる方、回答をお願いします。
176デフォルトの名無しさん:2007/09/30(日) 19:28:32
残念だったね。
177デフォルトの名無しさん:2007/09/30(日) 19:36:20
自分でマルチスレッド対応のストリームつくればいいじゃん
178148:2007/09/30(日) 19:44:05
>>177
そんな事したらめんどくさくないですか?
もうちょっと簡単な方法でお願いします
179デフォルトの名無しさん:2007/09/30(日) 19:49:11
そもそもプログラミング自体めんどくさくないですか?
ありあわせのフリーソフト探してくる方法が簡単だと思います
180デフォルトの名無しさん:2007/09/30(日) 20:50:56
そもそも生きてるってめんどくさくないですか?
氏ねば簡単ですよ
181デフォルトの名無しさん:2007/09/30(日) 20:56:18
>>180
どうやったら楽に死ねますか?
簡単そうな方法にはちょっと勇気が必要だし、そうでないのは簡単じゃないし
182デフォルトの名無しさん:2007/09/30(日) 21:09:17
>>180
旅立ちパックの中に
連単はいってるからつかえ
以上
183デフォルトの名無しさん:2007/09/30(日) 22:14:37
>181
死ねばすべてが楽になるんだ
楽したいなら、死ぬ努力ぐらいはしてもいいだろ
俺は死にたくないから、努力して生きるよ
184デフォルトの名無しさん:2007/09/30(日) 23:11:03
>>178
ストリーム出力だけロックすれば済む話だろうが〜
どこが面倒なんじゃ〜?
185デフォルトの名無しさん:2007/10/01(月) 01:35:10
マルチスレッドプログラミングは初心者には無理だよ
面倒=やり方がよくわからない という事であればこの先できるようになる見込みもなし
厳しいけどこれ現実なのよね
186デフォルトの名無しさん:2007/10/01(月) 03:15:20
スレッガーさん!
187デフォルトの名無しさん:2007/10/03(水) 20:59:05
スレッドセーフじゃない場合はどうするつもりだったのかと・・・
スレッドセーフだったらどうしたかったのかと・・・

まぁいいや、どうせネタでしょ?
188デフォルトの名無しさん:2007/10/08(月) 15:51:11
次世代ゲーム機のCPUみたいにレジスタが山ほどあるCPUて
コンテキストスイッチのオーバーヘッドも比例して増えてるんかな
189デフォルトの名無しさん:2007/10/08(月) 16:02:08
一部しか保存しなくてすむようにしてあんじゃね?IA64とかそうだべ。
190デフォルトの名無しさん:2007/10/08(月) 17:01:20
64bitのレジスタ32本あるのじゃまんぞくしねーのか?
191デフォルトの名無しさん:2007/10/08(月) 19:38:15
高速なキャッシュがたくさんあれば満足する
192デフォルトの名無しさん:2007/10/08(月) 20:11:01
IA64とかって確かコンテキストが2500バイトくらいいくんだよなw
193デフォルトの名無しさん:2007/10/09(火) 21:36:08
おれはレジスタの数よりも、1次キャッシュに乗ってるメモリとの
演算やアクセス速度が、レジスタと同程度であれば良いと思ってる。
結局それが最強でしょ?
194デフォルトの名無しさん:2007/10/09(火) 22:04:14
命令セットの問題じゃね
195デフォルトの名無しさん:2007/10/09(火) 22:47:19
だよね。
RISC系の、メモリアクセスは基本的にロード/ストアのみで
演算はレジスタに対してしか出来ない、ってアーキテクチャだと
キャッシュの速度だけじゃなく、レジスタの数も欲しいはず。
196デフォルトの名無しさん:2007/10/09(火) 22:58:57
そんなことできたら苦労は無いわ。
メインメモリにレジスタと同程度でアクセスできれば最強だな。
197デフォルトの名無しさん:2007/10/09(火) 23:43:09
>>196
補助記憶装置含めて光速の99%で処理できたらおk
198デフォルトの名無しさん:2007/10/10(水) 00:46:35
発想を逆にするんだ。
レジスタへのアクセスがメインメモリと同程度に遅(ry
199デフォルトの名無しさん:2007/10/10(水) 13:37:41
じゃあ、みんながのんびりすればよくね?
200デフォルトの名無しさん:2007/10/10(水) 18:07:14
俺も思う。
CPUだけじゃなくて、日本人がもっとのんびりスベキナンダヨ
201デフォルトの名無しさん:2007/10/10(水) 21:55:40
1ヶ月くらい休みクレ!
202デフォルトの名無しさん:2007/10/12(金) 23:27:18
>>>200
いや、今の状況はさー、
のんびりすべきだ、のんびりしよう、
とか言って急ブレーキ掛けてた頃からは、
実はもうだいぶ経っててさ、逆にのんびりしすぎてるんじゃ?
って密かに周りが焦り始めてるんだけど、
具体的な問題が出てくるまでは、それにあえて気付かない
フリをしていよう、ってところなんだよ。
ほんとうは、そろそろ歩きださないと。いそがないと!
って時なんだよ?
一度怠けると元に戻れなくなるって言うけど、それ以前に
元がどうだったかなんて忘れてるもんだからさ、
フリじゃなくてほんとうに気付いてないのかもしれないね。
日本ヤバイよー。
おれは海外に移住する予定です。
203デフォルトの名無しさん:2007/10/21(日) 20:33:43
SolarisでpthreadでC++です。

C* c;
int main() {
  c = new C;

と、mainの先頭で生成したオブジェクトを、N個のスレッド(実際は8個固定)から使っています。

スレッドが順次終了してゆき、最後のN個目が終了した直後、あるいはN-1個目が終了した
後かつN個目が終了する直前にdelete c;をしたいのですが、うまい方法はあるでしょうか。
リファレンスカウントでしょうか。

N個のスレッドすべてをpthread_join()するような、親スレッドはいません。
なお、Cのメンバ関数はすべてスレッドセーフに作られています。

よろしくおねがいします。
204デフォルトの名無しさん:2007/10/21(日) 20:36:29
>>203
リファレンスカウントで何か不満なの?
boost::shared_ptr ですぐに実装できそうだし。
205203:2007/10/21(日) 20:41:02
>>204
boostやSTLが使用禁止なので、一から手書きする場合の例をいただけたらと。。
テンプレートは使用可です。
206デフォルトの名無しさん:2007/10/21(日) 20:47:33
>>204
スレッドをまたいでshared_ptrを渡すのって例えばどうやるの?
207デフォルトの名無しさん:2007/10/21(日) 21:24:12
> boostやSTLが使用禁止なので

ぬふぅ
208デフォルトの名無しさん:2007/10/21(日) 21:24:57
>>203
代入系の演算子をoverrideしまくればそれっぽいの出来るけど、
用途をみてるとそれだけのためにshared_ptrを実装するのはもったいないな。
209デフォルトの名無しさん:2007/10/21(日) 21:45:00
>>205
boost の実装見ればいいじゃん。
210デフォルトの名無しさん:2007/10/21(日) 21:46:15
>>206
スレッドごとに shared_ptr のコピーを持てばいい。
211デフォルトの名無しさん:2007/10/21(日) 23:17:11
>>210
boostのshared_ptrの参照カウントの上げ下げってスレッドセーフだっけ?
最新のstableでもなにもしてなかったような。
212203:2007/10/21(日) 23:58:41
みなさまどうも。

>>210

shared_ptr<C> g;
int main() {
 g.reset(new C);
 // スレッドを8つ生成
 cond_wait; // スレッドがgをコピーするのを待つ
 g.reset(0);
 ...
}

void* thr(void* data) {
  shared_ptr<C> local = g;
  cond_signal;
  ...
}

とかですか。
213デフォルトの名無しさん:2007/10/22(月) 04:26:17
チラシの裏で悪いけど、g++のbits/atomicity.hの__exchange_and_add()とか使うと、
libstdc++.soの関数を呼びに行くんだね。おそそー。
214デフォルトの名無しさん:2007/10/22(月) 08:13:39
>>211
スレッドセーフではないとすると、参照カウントを上げる方は、
>>212のやりかたでも、一個ずつスレッドを作って、
cond_waitすればいいけど、下げる方は排他制御しないと
駄目って事かな?

単純な実装にするなら、
全スレッドが共用するカウンタを作って、上げ下げすればいいんじゃないのか?
最初と最後だけなら、速さとかは気にせずに、適当な実装でも問題なさそうだし、
atomicな操作ができるなら、それこそカウンタだけ渡せば済むし。

Cがいじれるなら、自分自身でカウントしても良さそうだけど。

どうでもいいけど、>>212は、グローバル以外の渡し方はないのか?
215デフォルトの名無しさん:2007/10/22(月) 16:47:54
>>214
void* data 経由で渡して、スレッド側でstatic_cat<shared_ptr<C*>* >することは可能。
スマートポインタへのポインタを渡すことになって気持ち悪いけど。
216デフォルトの名無しさん:2007/10/22(月) 18:27:07
どのみちmainは生きてるんだから
mainでjoinで待って削除すればいいのでは
217デフォルトの名無しさん:2007/10/22(月) 18:53:14
>>216

>>203
>N個のスレッドすべてをpthread_join()するような、親スレッドはいません。
218デフォルトの名無しさん:2007/10/22(月) 21:44:40
クラスCをsingletonにするのは無し?
219デフォルトの名無しさん:2007/10/22(月) 21:55:54
>>214
そうですね。スマートポインタは使わず、単純なカウンタ+アトミック操作でいこうとおもいます。

>>218
決してdeleteされないsingletonにするのはNGです。threadが全部いなくなったら、deleteしないとまずい
事情があります。

ありがとうございました。
220デフォルトの名無しさん:2007/10/22(月) 22:05:42
スレッドの調停者が居ない=全てのスレッドが終了時にアプリケーションが終了

なら,singletonでも別にもんだいねーよーな気がする
221デフォルトの名無しさん:2007/10/22(月) 22:12:26
>>220
スレッドが全部終了した段階では、アプリケーションは終了しません。
また、その段階で~C()をよばないと、いろいろまずいことがあります。


222デフォルトの名無しさん:2007/10/22(月) 22:19:30
>>220
誰がスレッドを最終的に所有してるの?
223デフォルトの名無しさん:2007/10/22(月) 22:22:45
素直にスレッドのマネージャを作れば
224デフォルトの名無しさん:2007/10/22(月) 22:25:30
>>222
メインスレッドaを起点として、ツリー状に生成・所有されています。

a-b-c-N1
   -d-N2
  e-f-g-N3
      -N4
   -h-N5-N6
   -N7
 -N8

みたいなひどい感じです。Nxが、今回興味のあるスレッド群。
何でこんなことになってるのかの経緯は、私にはちょっとわかりません。。。

225デフォルトの名無しさん:2007/10/22(月) 22:27:37
>>224

こんなはちゃめちゃになるんだったら
マネージャ作れよ

GCとかみたいに自分で管理したくないものは
誰か権限のあるやつだけに委譲しろよ
226デフォルトの名無しさん:2007/10/22(月) 22:28:56
>>225
managerとは、具体的には何をするものでしょうか?
227デフォルトの名無しさん:2007/10/22(月) 22:38:42
スレッドのリソースの管理
228デフォルトの名無しさん:2007/10/22(月) 23:06:01
>>227
ありがとうございます。

>>214
参照カウントは、http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2167.pdf あたりを参考にすればいいのかな。
4-8個程度はCPUの乗ったSPARCが相手だと、atomic_inc/decだけでは実装できないよね。このあたりに詳しいかた、コメント
いただけませんか?
229デフォルトの名無しさん:2007/10/22(月) 23:11:23
>>228
アトミックなカウンタ操作があっても実装できない理由って何?
230デフォルトの名無しさん:2007/10/22(月) 23:11:56
アトミック云々以前にスレッドの管理が出来てないんじゃ意味ないだろ
231デフォルトの名無しさん:2007/10/22(月) 23:15:43
>>229
複数のCPUが同時にatomic_incを実行すると破綻するから
232デフォルトの名無しさん:2007/10/22(月) 23:18:14
そんなのはアトミックじゃねぇ
233デフォルトの名無しさん:2007/10/22(月) 23:19:53
>>231
その atomic_inc はアトミックじゃないのかい?
234デフォルトの名無しさん:2007/10/22(月) 23:26:06
っSMP
235デフォルトの名無しさん:2007/10/22(月) 23:27:42
>>232-233
そういうCPUもあるし、そうでないCPUもある。
236デフォルトの名無しさん:2007/10/22(月) 23:35:39
そうでないCPUでは、それはただの x++ とどう違うの?
237デフォルトの名無しさん:2007/10/22(月) 23:47:52
>>236
横から。わたしもよくわかってないが
1.コンパイラやlibcが提供するatomic_inc/dec関数だけでは、単一CPUでのアトミックな演算しか保証されない
2.適切な命令(バリア)と一緒に使えば、複数のCPUを相手にatomicなinc/decができる (memory visibilityがどーたら)
3.どういうバリアが必要かは場合によって異なるから、コンパイラやlibcが提供するatomic_inc/dec関数にはバリアが入っていないことがある
こんなところじゃない?詳しい人フォローよろ。
238237:2007/10/22(月) 23:52:39
>>237
1と2の末尾にも「ことがある」を追加
239デフォルトの名無しさん:2007/10/23(火) 00:24:36
あー、そういう実装の既存の関数があるのね。

そこまで分かってるなら前後にメモリバリア足せばおしまいじゃね?
240デフォルトの名無しさん:2007/10/23(火) 00:29:35
つーかvolatileで十分w
241デフォルトの名無しさん:2007/10/23(火) 00:30:04
atomic_inc/readはlinuxのカーネル系の関数のようだね。
pthreadのような高位のAPIを使わない理由はなんだろう?
パフォーマンスを気にするようなアプリなのか。
242203:2007/10/23(火) 00:31:23
>>241
pthreadにします。
243デフォルトの名無しさん:2007/10/23(火) 09:00:33
>>240
キタ━━━━━━(゚∀゚)━━━━━━ !!!!!
244デフォルトの名無しさん:2007/10/23(火) 09:41:51
SPARCv9なら、CASがあるよ。
245デフォルトの名無しさん:2007/10/23(火) 17:58:33
linuxのCでスレッドの排他制御をしたいのですが、
なにぶんPONIX?っていうんですか?での開発は初めてなので
ご質問させてください。

pthread_mutex_t mutex;
pthread_mutex_init( &mutex, NULL );
pthread_mutex_lock( &mutex );
pthread_mutex_unlock( &mutex );
PONIXではこのようにpthread_mutex_lockを使うようですが
この引数pthread_mutex_t*をWin32のCreateThread()のように
ある共通の識別子を持っているスレッド同士のみが排他制御を
するにはどのようにすればよいのでしょうか?

例えば同じ親から4つ子のスレッドが生まれたとします。
スレッド長男と次男は排他関係
スレッド長女と次女も排他関係
でもスレッド男兄弟とスレッド女姉妹は排他関係ではない
という場合です。
246デフォルトの名無しさん:2007/10/23(火) 18:11:09
必要なだけ mutex を作って、自分で識別子と mutex の対応付けを管理する
247デフォルトの名無しさん:2007/10/23(火) 19:33:13
>>246 ありがとう。
248デフォルトの名無しさん:2007/10/23(火) 21:15:18
自分でご質問とか言うなよ
249デフォルトの名無しさん:2007/10/23(火) 21:29:36
なぜ?
250デフォルトの名無しさん:2007/10/23(火) 21:40:30
自分がする質問だから

「あなたのご質問には答えられません」
なら、相手を持ち上げている
「私のご質問に答えてください」
なら、自分を持ち上げている

日本人として変であることに気づくべき
251デフォルトの名無しさん:2007/10/23(火) 21:42:00
あほか
美化語を知らんのか
252デフォルトの名無しさん:2007/10/23(火) 21:47:44
おトイレならわかるがご質問はないな。
「ご質問はありますか」は当然あり。
253デフォルトの名無しさん:2007/10/23(火) 21:50:16
尊敬と謙譲の概念しか無いようだな。
254デフォルトの名無しさん:2007/10/23(火) 21:51:34
板違い
よそでやれ
255デフォルトの名無しさん:2007/10/23(火) 21:52:09
使い方が間違っているんだよ。
それを気づくことができないのか?
256デフォルトの名無しさん:2007/10/23(火) 21:54:16
257デフォルトの名無しさん:2007/10/23(火) 21:57:17
>>254
いやいや、質問する上でのマナーの話だからここで良い
マナーを守れない方がどっか行くべき
258デフォルトの名無しさん:2007/10/23(火) 22:00:35
>>257
いやいや、ご質問する上でのマナーのお話だからここで良い
おマナーをお守りできない方がどっかへ行くべき
259デフォルトの名無しさん:2007/10/23(火) 22:36:01
いや、マナーってほどの話ではないとおもう
変な日本語を使ってるけど、意味は理解できるから問題ない

てなわけで、おスレち
260デフォルトの名無しさん:2007/10/23(火) 22:41:30
やっぱ誰でもアクセスできるローレベルな話のほうが伸びるなw
261デフォルトの名無しさん:2007/10/23(火) 22:42:45
すまんなw
おれも、なんか参加しちゃってるよw
262デフォルトの名無しさん:2007/10/23(火) 22:44:37
しょうがねーな
俺も参加してやろうか
263デフォルトの名無しさん:2007/10/23(火) 22:46:22
僕もご参加していいですか?
264デフォルトの名無しさん:2007/10/23(火) 23:25:29
どうぞ、ご参加ください。
265デフォルトの名無しさん:2007/10/23(火) 23:36:57
珍しく盛り上がってると思ったら・・・

>>244
コード例
266デフォルトの名無しさん:2007/10/24(水) 01:46:21
ひさびさに来ましたよー
相変わらずスレ違いにはレス多いね。
267デフォルトの名無しさん:2007/10/24(水) 01:59:52
スレッドの呼び出しコストってどうやってはかるの?

組込み用でmutexとかの関数の呼び出しコスト一覧
表作り単位んだけどどうしたらいいん?
268デフォルトの名無しさん:2007/10/24(水) 02:27:13
>スレッドの呼び出しコスト
具体的にどういう意味と受け取ったらよいのだ?
269デフォルトの名無しさん:2007/10/24(水) 02:38:38
適当なタイマーで挟んではかr
270デフォルトの名無しさん:2007/10/24(水) 08:11:41
>>265
ttp://developers.sun.com/solaris/articles/stl-new.html
Standard Library, STL and Thread Safety
Atomic updates for reference counting

ttp://www.sparc.com/standards/SPARCV9.pdf
J Programming With the Memory Modelsにいろいろ
J.6 Spin Locks(Example 8―Lock and Unlock Using CAS)
J.11 Fetch_and_Add(Example 15―Fetch and Add Using CAS)
J.12 Barrier Synchronization(Example 17―Barrier Synchronization Using CAS)
J.13 Linked List Insertion and Deletion(Example 18―List Insertion and Removal)
271デフォルトの名無しさん:2007/10/24(水) 09:27:41
>>270
ktkr
272デフォルトの名無しさん:2007/10/25(木) 08:14:03
C++でのマルチスレッドに関する質問です
class sample{
private:
 int i;
 HANDLE hEvent;
public:
 sample(){
  hEvent = CreateEvent(NULL, TRUE, TRUE, L"sample");
 }
 ~sample(){
  CloseHandle(hEvent);
 }
 void fSetdate(int _i){
  WaitForSingleObject(hEvent, INFINITE);
  ResetEvent(hEvent);//ロック開始
  this->i = _i;
  SetEvent(hEvent);//ロック解除
 }
 int fGetdate(){
  WaitForSingleObject(hEvent, INFINITE);
  ResetEvent(hEvent);//ロック開始
  int _i = this->i;
  SetEvent(hEvent);//ロック解除
  return _i;
 }
}
273272の続き:2007/10/25(木) 08:17:17
上記のクラスをひとつだけインスタンス化して、
複数のスレッドがそれを呼び出した場合、データの同期化は成立しますか?
274デフォルトの名無しさん:2007/10/25(木) 09:08:53
何が死体のこれ?
275デフォルトの名無しさん:2007/10/25(木) 09:18:17
別々のスレッドがfSetdateのResetEventに同時に到達した場合どうすんの?
276272の続き:2007/10/25(木) 09:39:20
あべし

クラス内部でイベントによってデータの同期をとろうと思ったんですよー。
277デフォルトの名無しさん:2007/10/25(木) 10:03:47
何でCriticalSection使わんの?
278272:2007/10/25(木) 10:27:32
>>277
イベントと違いがわからんっす
279デフォルトの名無しさん:2007/10/25(木) 11:26:21
イベントを理解しとらんからだろ。
それで同期ってなにが目的なのよ?
280デフォルトの名無しさん:2007/10/25(木) 11:44:13
正解を書きたいけど、それをコピペして終了されると悲しいので
ここは是非MSDNのドキュメントを読むなりして頑張って欲しい。
281デフォルトの名無しさん:2007/10/25(木) 13:10:53
>>278
イベントとクリティカルセクションがどう違うかなんて、腐るほど説明があるから
いちいち書きたくないが、簡単に言うと

・イベント
遅い
プロセス間の同期に使える

・クリティカルセクション
速い&簡単
スレッド間の同期にしか使えない

あと、その目的でイベントを使うなら自動リセットイベントを使う。
そのコードだと275の懸念していることが、起こるかもしれないという
レベルではなく、確実に起こる。
282デフォルトの名無しさん:2007/10/25(木) 13:20:09
何をどう同期したいのか分からんから起こっても変わらん気がするw
283デフォルトの名無しさん:2007/10/25(木) 15:43:08
>>281
初心者に、あまり適当なこと教えるなよ。
それはどちらかというと、MutexとCRITICAL_SECTIONの違いだろ。

EventとCRITICAL_SECTIONの違い、あるいはpthreadにおけるcondとmutexの違いは
同期(実行をコントロールする)か排他(データを保護する)か。
284272:2007/10/25(木) 18:24:31
みなさんどうもっす。
同期について根本的に勘違いしてました。
データの保護ではCriticalSectionを使うのですね。

でもEnterCriticalSection()が同時に
実行されるということはありませんか?
285デフォルトの名無しさん:2007/10/25(木) 18:31:20
そんな質問が出るってことは
まだCriticalSectionについてググってすらいないようだな…。
286デフォルトの名無しさん:2007/10/25(木) 20:26:43
>>284
>でもEnterCriticalSection()が同時に
>実行されるということはありませんか?
わらった。
そりゃ同時に実行されるさ。そのためのものだもん。
287デフォルトの名無しさん:2007/11/12(月) 14:38:05
質問。
今のところはlinuxのpthreadのみを使っていますが、
なるべく一般のスレッドで使えるようにしたいと考えています。

複数のスレッド(X,Y,...)があってそれぞれが独立に動き、
読み込みアクセスrdと書き込みアクセスwrをします。
排他の条件は
1) XのrdとYのrd =>排他しない
2) XのrdとYのwr =>排他する
3) XのwrとYのwr =>排他する
4) XのwrとXのrd => 排他しない(wrの中からrdすることがあるので)
となっています。

自力で考えた手法はrwlockを使っています。
4)の条件を満たすためにrでロックする際はtryrdlock()して
・返り値がEDEADLKなら自スレッドがwrlockしているとみなしてロックせずに通す
・それ以外なら他スレッドがwrlockしているとみなして待機する
としています。
この手法で移植性は十分でしょうか?
288デフォルトの名無しさん:2007/11/12(月) 14:58:54
移植性っても、どの程度を考えてるかによるけど、例えば Windows には reader writer lock がそもそもなかったような…
289デフォルトの名無しさん:2007/11/12(月) 22:10:34
visutaから追加された。
290デフォルトの名無しさん:2007/11/12(月) 22:15:25
びじゅた?
291デフォルトの名無しさん:2007/11/12(月) 22:25:14
一般のスレッドって何だよ
292デフォルトの名無しさん:2007/11/12(月) 22:38:23
なんで4)でrdロックする必要あるの?
293デフォルトの名無しさん:2007/11/12(月) 23:47:18
ぴゅうた以来
プログラムかいてねーから
鈍ってしまって困った
294デフォルトの名無しさん:2007/11/13(火) 09:52:33
返答ありがとうございます。

>>288
Windowsのスレッドは触ったことがなく、rwlockがないことを知りませんでした。

>>292
rwlockの状態を知るためにtrylock()しています。
pthreadに現在の状態を問い合わせる関数が見付からなかったのでこのようにしました。
(一般には現在の状態を問い合わせても
次のステップまでその状態が持続するとは限らないことは承知しています)

mutexからrwlockを実装するというのを本で読んだことがあるので
それを参考に実装してみます。
295デフォルトの名無しさん:2007/11/15(木) 00:30:34
Linuxでpthreadを使用しているのですが
valgrindで実行するとfopenとfcloseの箇所で以下のエラーが大量に出ます。

==25540== Possible data race reading variable at 0x1D52238C
==25540== at 0x674CB5: _IO_un_link_internal (in /lib/tls/libc-2.3.4.so)
==25540== by 0x668A5D: _IO_fclose@@GLIBC_2.1 (in /lib/tls/libc-2.3.4.so)
==25540== Address 0x1D52238C is 52 bytes inside a block of size 352 alloc'd by thread 1
==25540== at 0x1D4A8090: malloc (vg_replace_malloc.c:131)
==25540== by 0x66935E: __fopen_internal (in /lib/tls/libc-2.3.4.so)
==25540== by 0x66941C: _IO_fopen@@GLIBC_2.1 (in /lib/tls/libc-2.3.4.so)

Webで調べるとglibcはすべてスレッドセーフだと書かれているのですが
同期とかしないといけないのでしょうか?
詳しいかた教えてください。
296デフォルトの名無しさん:2007/11/15(木) 03:10:57
helgrind使ってるって事?
あとさ、glibc-2.3.4って偉い古いな。
297デフォルトの名無しさん:2007/11/15(木) 03:13:19
関数がスレッドセーフであるかと同期が必要かは別問題
298デフォルトの名無しさん:2007/11/15(木) 03:40:30
>>295
同じdescriptorを同時にopen/closeしにいったらまずいわな。歯痛汁。
299295:2007/11/15(木) 12:29:07

>>296
CentOS4.5でhelgrind(valgrindは2.2)です。
yumしてみましたがglibcのバージョンは2.3.4が最新でした。

>>297
すみません、語弊がありました。
glibcがスレッドセーフでないならなにか回避策がないと
スレッドでは使用できなくなってしまうので一般的にはどうするのかなと。

>>298
すみません、説明が足りませんでした。
ファイルのオープン、リード、クローズは
すべて同一のスレッド内で行っています。
300295:2007/11/15(木) 12:30:35
みなさん遅くにありがとうございます。
もう少し調べてみます。
301デフォルトの名無しさん:2007/11/15(木) 22:26:00
valgrind3.3まで待ったら?
302デフォルトの名無しさん:2007/11/17(土) 00:08:19
同僚に嫌がらせするだけのために

valgrind --tool=erogrindって
オプション作って

オワタって表示されるようにしたんだけど
さっきめっさ怒られたw
303デフォルトの名無しさん:2007/11/17(土) 20:28:57
思いつきだが、最新のvalgrindのsupression fileを使ってhelgrindしてみるのはどうだろうか。
304デフォルトの名無しさん:2007/12/18(火) 09:21:07
Linuxを使った組込機器の開発に、NPTLではなくLinuxThreadsというのを使うことになりました。
これは聞くところによると、あまりOSに頼らずに実装されたスレッドライブラリということですが、
たとえばpthread_mutex_lock関数はどのように実装されているのでしょうか?OSのシステムコール
を呼ばない形で実装されているのでしょうか?

ソース嫁かもしれませんが、詳しい方いらっしゃいませんか?
305デフォルトの名無しさん:2007/12/18(火) 09:55:20
306デフォルトの名無しさん:2007/12/18(火) 11:18:26
アトミックオペレーションができるインストラクションをインラインアセンブラーで記述する事で実現している
307デフォルトの名無しさん:2007/12/18(火) 21:23:24
しばらくspinしてもロック獲得できなかったらRTシグナル街に入るんだっけ?
それはともかく、俺は完全ユーザ空間な1:Nスレッドの実装方法、特にどうスレッドをスケジュールするのかがさっぱりわからない。
308デフォルトの名無しさん:2007/12/18(火) 21:48:30
green thread
309デフォルトの名無しさん:2007/12/18(火) 21:49:42
>>308
解説よろ
310デフォルトの名無しさん:2007/12/19(水) 23:15:10
pthread規格で、
・端末で^CしたときのSIGINTシグナルは、どのスレッドに届くのか(あるいは全スレッドに届くのか)
・メインスレッドがexit()するとその他のスレッドは終了するのか
・メインでないスレッドがexit()したときはどうか
がわかりません。規格上どうなっているか、あるいは最近のLinuxでどうなるか教えていただけないでしょうか?
手元にSolarisしかなくて困ってます。

あ、main関数を実行したスレッドを勝手にメインスレッドと呼びました。
311デフォルトの名無しさん:2007/12/19(水) 23:39:05
>>310
プロセス宛てのシグナルは、どれか一つのスレッドに届く。どれに届く
かは決められていないので、受け取りたいスレッド以外ではそのシグナ
ルをブロックするようにしておく。

exit()でプロセスが終了する。スレッドは関係ないはず。

312デフォルトの名無しさん:2007/12/19(水) 23:39:21
スレッドセーフレベルの統一的な呼称ってあります?
引数がスレッドセーフじゃないとか条件付の状態とかあるよね。
313デフォルトの名無しさん:2007/12/20(木) 11:07:35
シグナル受け専用スレッドって作る?
314デフォルトの名無しさん:2007/12/22(土) 20:32:00
waitして何かあったらコールバックしてる。
315デフォルトの名無しさん:2007/12/23(日) 19:58:10
pthread_cond_wait()でspurious wakeupが起こるのって具体的にはどういうときでしょうか?
どういう順番で、各スレッドの実行や切り替えが起こった場合でしょうか?
316デフォルトの名無しさん:2007/12/23(日) 20:05:52
.NETのMonitor.Waitでもおこるかどうか知ってる人いませんか?
317デフォルトの名無しさん:2007/12/23(日) 20:14:35
3000円ちらつかせると
解ってくるかもしれないw
318デフォルトの名無しさん:2008/01/01(火) 20:48:11
>>315,316
マルチスレッドプログラムは基本的に非同期なので、何がおきても対応できるように冗長に作っておいたほうがいいと思う。

319デフォルトの名無しさん:2008/01/01(火) 23:44:58
>>318
何も言ってないのと同じw

「基本的に」「何がおきても」「冗長に」って.....いかにも何も判ってない奴が使いそうなワードを連発されてもなぁ。
320デフォルトの名無しさん:2008/01/02(水) 00:04:00
代わりに君が内容の有る事を言ってもいいんだよ
321デフォルトの名無しさん:2008/01/02(水) 00:20:32
そんなものが書けると思っている段階でダメダメ
322319:2008/01/02(水) 00:24:53
>>315 >>320
まず、cond_waitしているスレッドがシグナルを受信し、cond_waitがEINTRで戻った場合。

もうひとつ、これをspurious wakeupと呼ぶかは語の定義によるが、cond_wait中のスレッドがwakeさせられた際、
mutexをlockする前に別のスレッドがmutexを先にlockし、条件を偽にした場合。

どちらも、POSIXでは起きてよいことになっているけど、本当に起こり得るかどうかは実装による。

>>316
知らん
323デフォルトの名無しさん:2008/01/02(水) 00:34:36
324デフォルトの名無しさん:2008/01/02(水) 00:38:35
>>295
去年の12月にhelgrindの新しいの出たらしいよ。
325デフォルトの名無しさん:2008/01/03(木) 09:46:44
>>295
複数のスレッドからアクセスすれば
"Possible" data race
になるのは当然なような
俺はそういう作り方はしない
326デフォルトの名無しさん:2008/01/05(土) 01:33:19
>>295
ファイル操作用のスレッドかなにかに
終了通知送って閉じさせろよ

資源の管理はよほどの事情ないかぎり
一括にしろ
いいなわかったか?反論するなら
お前の家にそれは末恐ろしいものを
いくつかぶちまけて逃走するからな?

いいかわかったか?
327デフォルトの名無しさん:2008/01/06(日) 23:38:52
C言語でマルチスレッドに挑戦していまして、
複数の子スレッドを途中停止させ、また再開できるような状態にしたいのですが、
いい方法はありませんか?
328デフォルトの名無しさん:2008/01/06(日) 23:41:50
>>327
Cでどうやるのか忘れたけど、イベントなりセマフォなりミューテックスなりで待たせるのが
一般的。
329デフォルトの名無しさん:2008/01/06(日) 23:47:25
>>327
pthread_barrier_wait()
とエスパー。
330デフォルトの名無しさん:2008/01/07(月) 02:21:07
>>327

C言語にスレッドという概念はない。
環境書かないとわかんないよ。
331デフォルトの名無しさん:2008/01/07(月) 09:38:37
WindowsXPです。
332デフォルトの名無しさん:2008/01/07(月) 10:22:58
>>331

Winなら、MFC使ってUIスレッド作って、メッセージで動かすのが簡単だが。
Win32APIだけでやりたかったら、↓のマルチスレッドの章を一通り読んでみ。87章から。
http://www.kumei.ne.jp/c_lang/index_sdk.html

WaitForSingleObject() あたりを使うことになるだろうな。89章から先に載ってる。
333デフォルトの名無しさん:2008/01/07(月) 11:51:27
レスありがとうございます。
調べましたところ、
WaitForSingleObjectはスレッドがシグナル状態になるまで待ち合わせを行うものだとありましたが、
これをどのように使えばスレッドを途中停止出来るのでしょうか?
334デフォルトの名無しさん:2008/01/07(月) 11:55:26
>>333
スレッドで考えるんじゃなくて二人以上の作業者による連携プレーを考えろ
で、ひんとはミューテックスオブジェクトかセマフォオブジェクト
335デフォルトの名無しさん:2008/01/07(月) 13:15:18
スレッドを止めたいって書いてあるのが読めないのか?
答えられないならレスするんじゃねぇよ。
336デフォルトの名無しさん:2008/01/07(月) 13:25:13
>>335 をつつくとSuspendThread使えとか言い出しそうだな(笑
337デフォルトの名無しさん:2008/01/07(月) 13:30:41
「いい方法はありません」ってことで。
338デフォルトの名無しさん:2008/01/07(月) 15:08:45
>WaitForSingleObjectはスレッドがシグナル状態になるまで待ち合わせを行うものだとありましたが、

調べが足りてないね。
339デフォルトの名無しさん:2008/01/07(月) 15:13:49
Windowsなんて使ってるやつは馬鹿です
340デフォルトの名無しさん:2008/01/07(月) 15:21:29
>>339
なぜですか?
341デフォルトの名無しさん:2008/01/07(月) 19:32:15
「ATOK使うやつは馬鹿」と何かの関係が!?
342デフォルトの名無しさん:2008/01/07(月) 19:33:09
ここは良心的な釣堀か。入れ食いだな。
343デフォルトの名無しさん:2008/01/07(月) 19:44:14

なぜ止めたいかを説明してケロ。
他のスレッドを強制的に止めたいのか、何かを待ちたいのか。
スレッドを止める方法はいろいろあるので、目的を説明して。
344デフォルトの名無しさん:2008/01/08(火) 03:46:58
個人中傷スレだったので・・・
345デフォルトの名無しさん:2008/01/12(土) 13:01:16
スレッドじゃないけど

fork()類って実行間隔って
あまりにも短いとダメなのかな?
346デフォルトの名無しさん:2008/01/12(土) 14:11:33
>>345
なんで?
347デフォルトの名無しさん:2008/01/12(土) 14:21:25
>>30msに一度呼ぶと
失敗するような気がするw

348デフォルトの名無しさん:2008/01/12(土) 14:27:36
>>347
それシステム資源食い潰してるしwww
349デフォルトの名無しさん:2008/01/12(土) 14:28:09
そもそもなんでそんなにfork()しなきゃならんのかと。
設計から見直せ。
350デフォルトの名無しさん:2008/01/12(土) 14:31:43
>>349
fork()する回数は10回なのですが
なるべく速くfork()を10回完了させたいだけですw
351デフォルトの名無しさん:2008/01/12(土) 14:33:43
OSくらいさらせや
352デフォルトの名無しさん:2008/01/12(土) 14:34:37
>>350
exec
353デフォルトの名無しさん:2008/01/12(土) 14:43:39
ちなみにSolaris 10 で
のことです
354デフォルトの名無しさん:2008/01/12(土) 17:20:58
errno は?
355デフォルトの名無しさん:2008/01/12(土) 17:30:49
ダメって何がダメだったのか・・・
356デフォルトの名無しさん:2008/01/12(土) 22:41:41
>>350
preforkしろ
357デフォルトの名無しさん:2008/01/13(日) 08:22:40
アセンブリでマルチスレッド
これ最速
358デフォルトの名無しさん:2008/01/13(日) 13:26:49
同期とかも全部asmでやるの?
359デフォルトの名無しさん:2008/01/13(日) 19:16:03
spin lock
360デフォルトの名無しさん:2008/01/13(日) 20:38:31
>>359
fairnessの問題はどうする?
361デフォルトの名無しさん:2008/01/14(月) 13:48:04
fairlock
362デフォルトの名無しさん:2008/01/14(月) 18:00:45
【OS】Windows Vista Ultimate

【言語】C++

【実行環境】Visual C++ 2005 Professional, C++ Boost Library 1.34.1

【その他突起する事項】なし

bool shouldExit_;
istream &is;

void handler()
{
while(!shouldExit_)
{
string str;
is >> str;
}
}

handler関数がthreadのコールバック関数になるのですが
この関数を終了させようとしてshouldExit_にtrueを代入しても
入力が内場合、入力演算子を使用しているところでずっと待機してしまいます。
このスレッドを安全に終了させる方法はないでしょうか?
363デフォルトの名無しさん:2008/01/14(月) 18:06:54
>>362
volatile bool shouldExit_=false;
364306:2008/01/14(月) 18:08:38
すみません。
漏れていました。
本来のコードには書いてあるのですが、shouldExit_を評価するところまで処理を持って行けません・・・。
365デフォルトの名無しさん:2008/01/14(月) 18:09:13
>>363
をいをい w
is>>str; でブロックされてるんだからこの場合フラグは関係ないだろ。

とりあえず入力をタイムアウト付きでやるか(C++でどうやるかは知らん)、
可能なら入力ストリームをクローズしてしまえ。
366デフォルトの名無しさん:2008/01/14(月) 18:51:35
入力を待つけどキャンセルとか強制終了出来るようにしたいんだろ?
367361:2008/01/14(月) 19:55:45
>>365
istreamの実態はネットワークなので
まさにその方法でうまくいきました。
ありがとうございます。

>>366
もしそれができればそうしたいです。
なるべくstreamに影響を与えたくないです。
368デフォルトの名無しさん:2008/01/14(月) 22:15:59


【OS】 linux fedora 7
【言語】 C
【実行環境】 えー?何て書けばいいのかな?
【その他突起する事項】 特になし

質問ですが、何故pthread_createの第4引数はvoidでキャストするの?
argを入れるんだし。たとえば、整数 2を入れる場合も
(void *)2
みたいに渡しますよね。
構造体に渡すと言ってもポインタで渡したら良いだけのような....

そのまま入れたらダメな理由は何ですか?
教えてえろい人
369デフォルトの名無しさん:2008/01/14(月) 22:29:32
なにをやろうとしているかを理解してからやれ、ということ
370デフォルトの名無しさん:2008/01/14(月) 22:31:38
そういう関数作って
そのままいれてみろ
371デフォルトの名無しさん:2008/01/14(月) 22:32:38
>>368
日本語でおkだよ
372デフォルトの名無しさん:2008/01/14(月) 22:34:33
>>368
32bitで済むなら、キャストして無理やり渡したほうが楽ジャン
373デフォルトの名無しさん:2008/01/14(月) 22:35:30
>>369-370
あ、ありがとう。

理解が足りないかもですね。

(int *)でも良いんじゃないですか?って思うんです。

やってみたけど、ダメだよー
なんです。orz
374デフォルトの名無しさん:2008/01/14(月) 22:36:23
あ、64bit環境 gccです
375368:2008/01/14(月) 22:37:13
373,374も私です。
376デフォルトの名無しさん:2008/01/14(月) 22:39:18
LP64環境か。なら、(void*)2ULLじゃねーの?
377デフォルトの名無しさん:2008/01/14(月) 22:40:18
void* argを数値に戻すときは、int i = (int)(unsigned long long)arg;
378368:2008/01/14(月) 22:47:29
>376
(void*)2
で動きます。
プリプロセッサがそのように直しているのかも知れません。

>>377
ん?
pthread_create(&th , arg2 , arg3, (void *)2);
みたいに渡しますが
pthread_create(&th , arg2 , arg3, (int *)2);
ではダメな理由は何ですか?
379デフォルトの名無しさん:2008/01/14(月) 22:47:42
uint64_tって書けよw
380368:2008/01/14(月) 22:50:20
uint64_tもダメでした
キチンとかかず、ごめんなさい
381デフォルトの名無しさん:2008/01/14(月) 22:53:52
>>380
お前だめだわ

pthread_create()のmanみて
引数の定義どうなってるか調べたか?

そこは何でも受け取れるようにvoid *になってるから
そう渡せやって定義に書いてあるだろボケ
東京湾に沈めるぞドあほ
382368:2008/01/14(月) 22:57:43
>>381
man見てますよ。

なぜvoidでキャストするの?int*とかでも良いでしょ?ポインタで渡すだけでしょ?
ってことなんです。
383368:2008/01/14(月) 22:59:01
ポインタで渡す限りintもcharもvoidも関係ないでしょ?って質問です
384デフォルトの名無しさん:2008/01/14(月) 23:00:55
>>382
なんでint *なの? 汎用ポインタならvoid *が判りやすくていいじゃん。
# それとも、qsort()も使ったことがない人?
385デフォルトの名無しさん:2008/01/14(月) 23:01:29
C言語の型って何のためにあるかわかる?
386デフォルトの名無しさん:2008/01/14(月) 23:06:28
関係ないけどC99では整数⇔ポインタ変換する場合はintptr_tを使った方がよくて、
それやらないと最悪strict aliasingの最適化でバグっちゃうケースがあるらしい。
387368:2008/01/14(月) 23:08:43
>>384
>汎用ポインタならvoid *
大抵、そうですね。
昔、voidに型は無い、という話だったけど、void型という型になっていて浦島
状態です。

>>385
話の流れから、メモリ確保の為。
intのサイズは小さく、他に大きなサイズの時困るって事でしょうけど。

今回は、pthread_create(&th , arg2 , arg3, (int *)2);
のように、サイズが小さくても、不整合は出ないような...
出るのかな?
388デフォルトの名無しさん:2008/01/14(月) 23:13:41
いや、Cにはvoid型はないけどvoid*型はあるの。
389デフォルトの名無しさん:2008/01/14(月) 23:17:11
void型はあるよ。
void型へのキャストもできるし。
390デフォルトの名無しさん:2008/01/14(月) 23:17:48
>>387
サイズ云々はかんけーねーだろ
8byteの汎用アドレス渡すことに
何一々屁理屈こねてるんだアスペル房?

391デフォルトの名無しさん:2008/01/14(月) 23:20:22
>>368
あるよ
392368:2008/01/14(月) 23:20:31
>>390
>385は何のため?

>>389
void型って、出来てますよね?
393デフォルトの名無しさん:2008/01/14(月) 23:20:42
>>387
考えがアセンブラだなぁ。
ひょっとして今時オブジェクト指向を理解できてない人?
394368:2008/01/14(月) 23:22:59
>>393
確かに gcc -Sのコード見たほうがデバッグ早いです。

オブジェクト指向は、時々する程度です
395デフォルトの名無しさん:2008/01/14(月) 23:23:51
>>392
厳密に型が決まってる言語だから
その場合に曖昧さを表現するには
C言語の場合、簡単な解決方法は
void *で表現すること
理解できないみたいだし四ねw
396デフォルトの名無しさん:2008/01/14(月) 23:27:08
void hoge(void) {
return (void)0;
}

規格にも void type とかいう用語は出てくる。
397デフォルトの名無しさん:2008/01/14(月) 23:27:48
>>395
理解しますが
>簡単な解決方法void *で表現
ならば、他に方法は有るのですか?無いのですか?
398デフォルトの名無しさん:2008/01/14(月) 23:31:34
値は同じでも意味が違うものってあるでしょ。
C言語でいうなら同じ0でも、数学の0と、ポインタのNULLでは意味が違う。
それらを区別するために型という概念がある。
で型があることでコンパイル時に型チェックが可能となって意味の混同が起こってないかを調べられるわけ。
399デフォルトの名無しさん:2008/01/14(月) 23:35:53
引数に int* ってあるなら、それは32bitの値へのアドレスを渡すということではなくて
intの意味を持ったものへのポインタを渡すって理解すべきなの。
だからそこへとある構造体へのポインタを渡すなんてのは設計も使い方も分裂症気味におかしいわけ。
400368:2008/01/14(月) 23:43:00
>>398,399
なるへそ。分かりました。

けど、別の疑問が、**(ポインタのポインタ)で渡したら型の意味もないような
401デフォルトの名無しさん:2008/01/14(月) 23:45:46
どうでもいいけど、(void *)2はともかく、(int *)2はきもい
402デフォルトの名無しさん:2008/01/14(月) 23:51:41
*が何個付こうが話は同じ
403368:2008/01/14(月) 23:59:01
了解。
皆さんありがとうーーーーー。
関数作ってみようか考えていましたが、しなくて良いみたいですね
404デフォルトの名無しさん:2008/01/15(火) 00:31:43
やけにスレが伸びてるなと思ったらC言語講習会かよ・・・
405デフォルトの名無しさん:2008/01/15(火) 00:34:54
じゃ、pthread_atfork関係でもする?
406デフォルトの名無しさん:2008/01/15(火) 00:37:40
pthread_yield()で頼む。
NPだけど。
407デフォルトの名無しさん:2008/01/15(火) 00:44:56
なんで?
408デフォルトの名無しさん:2008/01/16(水) 01:36:25
スレッドで thread1 thread2の2つを走らせている場合
正常狩猟、異常終了両方で2つのthread1 thread2とも同時に終了させて
再度、起動したいのですが、どのようにして終了させたら安全ですか?

pthread_cancel(),ptrhread_join,pthread_exit
409デフォルトの名無しさん:2008/01/16(水) 02:31:14
>>408
スレッドを抜ける
410デフォルトの名無しさん:2008/01/16(水) 04:51:33
>>409
そりゃそうだ。
cancel-join
exit-joinが良いのかな?
どうしたら良いかな?
mutexは無しです
411デフォルトの名無しさん:2008/01/16(水) 11:27:19
thread10個起動して、全部待ちたいときはどうすればいいの?
412デフォルトの名無しさん:2008/01/16(水) 11:33:00
forでjoin回せば。Win32なら64個までの限定だけどWaitForMultipleObjectsとかあるけど
413デフォルトの名無しさん:2008/01/16(水) 11:37:22
>>411
pthread_barrier_wait()
414デフォルトの名無しさん:2008/01/16(水) 21:02:03
あざーす。
415デフォルトの名無しさん:2008/01/17(木) 00:19:01
すみません
スレッドでがんがん動く関数がるけど、この関数は起動字にも動いて処理します。
起動字はスレッド起こしてないんだけどpthread_関係が入っている関数を使っていいの?
具体的にはpthread_atporkです
416デフォルトの名無しさん:2008/01/17(木) 00:58:36
誤時がおおおいな
417デフォルトの名無しさん:2008/01/17(木) 01:38:20
あっとぽーくなんてマニアックな関数、何に使うんだか。
418デフォルトの名無しさん:2008/01/18(金) 01:50:30
deadbeefと関連がありそうだな
なさそうでもあるな
419デフォルトの名無しさん:2008/01/18(金) 22:47:59
>>413

411じゃないけど、pthread_barrier_wait() はlinuxでは無いようです。
どうようの効果を期待できる関数は何ですか?あるいは、その組み合わせは?
教えてちゃんですまそん
420デフォルトの名無しさん:2008/01/18(金) 23:57:18
>>419
あんたの使ってるディストリビューションが古いだけ。
もっと新しいglibcを積んでるやつを使え。
421デフォルトの名無しさん:2008/01/19(土) 00:46:44
LinuxThreadsの頃からあったと思うんだがな。。。
何使ってんだ??
422デフォルトの名無しさん:2008/01/19(土) 00:48:06
>>419
ほんとにないなら、mutexと条件変数の組み合わせで実現できるけど、結構難しいよ。
NPTLのpthread_barrier_waitの実装を読んで、真似するのが良いと思う。
423419:2008/01/19(土) 02:35:01
>>420,421
cg-linuxていうらしいです。manで無かったんです
かえたらダメだと思います。多分。
kernel=2.4.17?みたいなことします。

pthread.hを見て本当にないか見てみます。

>>422
そんなドキュメントあるんですか、本当になかったら探します。
424デフォルトの名無しさん:2008/01/19(土) 06:58:09

私が小学生の頃、
日本中でノストラダムスの予言が大流行していた。
「1999年の7月に人類は滅亡する!」
という例のお騒がせ終末予言である。

大人になって社会に出て働きだして、
あくせくと忙しく日々を過ごしながら、
1999年は、
ありふれた日常の中であっさりと過ぎていった。
人類は滅ばなかった。

これからここで、
1999年に起こるかもしれなかった人類の壊滅的破局を、
誰にも知られずにこっそりと回避させた人たちがいた...
という設定で、
荒唐無稽なストーリーを描いてみたい。
無論、100%完全なフィクションである。

http://www5.diary.ne.jp/logdisp.cgi?user=532063&log=200705
425デフォルトの名無しさん:2008/01/20(日) 00:09:05
426デフォルトの名無しさん:2008/01/23(水) 02:29:53
>>425
くーーー、64bitなんですーーー
探してみますーーーー
こんなサービスもあっ短だメモメモ
427デフォルトの名無しさん:2008/01/23(水) 05:25:11
bit数関係あんの?
428デフォルトの名無しさん:2008/01/23(水) 14:35:26
cglinuxってキャリアグレード?
429デフォルトの名無しさん:2008/01/24(木) 00:25:00
そうだろうね。カーネルバージョン見ると MontaVista っぽい。
だとするなら、サポートしてるかどうかはもんたに聞いた方が良いね。

というか、419が欲しい機能は本当にpthread_barrier_waitで合ってるんだよね?
>>411 を素直に読むと >>412 で FA だと思うんだが。
(まあ419がちゃんとわかってて聞いてるなら余計なお世話だけど)
430デフォルトの名無しさん:2008/01/24(木) 15:23:46
matrix * matrixをpthread_createとpthraed_joinだけで、
ぶん回してみたけど(quad core)普通にthread無しで
やるほうがはるかに早かった。

pthread_createのコストが高いのかなあ?
threadを最初に作っておいてpthraed_cond_wait待っておいてスレッドを使いまわす
方式で再実装してみる。
431デフォルトの名無しさん:2008/01/24(木) 15:55:51
スレッド数4にしてる?
432デフォルトの名無しさん:2008/01/24(木) 16:25:48
している/いろいろやってみだ。
4,10,,12,16,32

32だと、たまーにtopでみていると2000%とかになっていた。
それでも、遅い。
433デフォルトの名無しさん:2008/01/24(木) 16:27:54
×みだ
○みた

あと、スレッド数8が抜けていた。
434デフォルトの名無しさん:2008/01/24(木) 19:28:15
コアが4個なんだからそれより多くしてもほとんどメリットはないだろ
435デフォルトの名無しさん:2008/01/24(木) 19:31:44
プロセス生成に比べるとマシってだけで、
スレッドの作成(と終了)はそれなりにコスト高いよ。
436デフォルトの名無しさん:2008/01/24(木) 19:36:38
並列化効率とかアムダールの法則とかでググれ
437デフォルトの名無しさん:2008/01/24(木) 23:34:00
DualCoreXeon*2で実験した限りでは、core辺り処理量は(殆ど)変わらなかったけどなぁ。
分割の仕方が悪いんで内科医?
438デフォルトの名無しさん:2008/01/25(金) 06:20:13
>>436
そんなの、スレッド本の第一章に書いてあるだろ。
439デフォルトの名無しさん:2008/01/26(土) 13:54:13
Windowsで
4つのスレッドを開始させ、
一つのスレッドが終了次第、
ほかのスレッドも全て終了させる方法ってありますか?
440デフォルトの名無しさん:2008/01/26(土) 14:02:01
>>439
そのように作ればそうなります。
441デフォルトの名無しさん:2008/01/26(土) 14:07:17
>>440
すみません。
私の聞き方が曖昧でした。
手段を教えて下さい。
442デフォルトの名無しさん:2008/01/26(土) 14:31:08
終了すると終了させるは微妙だが大きな違い
443デフォルトの名無しさん:2008/01/26(土) 14:37:11
>>439
4人の子供のうち、誰か一人でも死んだという通知が来たなら、他の三人に死亡要求を掛ければよろしいかと。
子供が死亡要求を聞き届けてくれない仕様ならば、殺すしかありませんが。
いずれにしても、APIレベルで実装したいならAPIスレ、.Netでやりたいなら.Netスレ、そうでないならVSスレなり
初心者スレなり適当にどうぞ。
444デフォルトの名無しさん:2008/01/26(土) 14:41:02
WaitForMultipleObjectsで4つのスレッドを待てば、どれか一つのスレッドが
終了したかが判るから、あとは終了イベントたてるなり(スレッドが参照していることが条件だけど)、
TerminateThreadするなり(非推奨)、好きなようにやれば。
445デフォルトの名無しさん:2008/01/26(土) 14:54:02
マルチスレッド使って、CPU負荷分担みたいなことってできる?
2つのまったく動作が同じスレッド作って、2つのCPUリソースに処理を振り分けるとか?
446デフォルトの名無しさん:2008/01/26(土) 15:25:58
できるできないで言えば普通できるに決まっとろう。
447デフォルトの名無しさん:2008/01/26(土) 16:19:18
なにか共通で使うリソースがあって、同時にそれを使えない場合は、
如何に競合を回避するか考えないと、相手のリソース解放を待つのとかで、
同時に動作できる時間が減っちゃう。
CPU1: *-*-*    ***---
CPU2: -*-*- とか ---***
こんなのになったら意味無いし。
448デフォルトの名無しさん:2008/01/26(土) 18:09:47
無駄だけどセマフォしかないわ、全部持つか、一個なら諦めろw
449デフォルトの名無しさん:2008/01/26(土) 21:55:22
Windowsでは、有限バッファ問題(生産者消費者問題)はどう解決するのが良いでしょうか?
http://www.cs.is.noda.tus.ac.jp/~mune/oop/node16.html

生産者も消費者も単一プロセス内のスレッドで、生産者・消費者はそれぞれ複数いるという
状況です。バッファがfullまたはemptyのときは、pushまたはpopの処理がブロックしてかま
いませんが、バッファ長は1や2ではなくもう少し大きくしたいと思っています。

UNIXだと、条件変数かセマフォを使えば簡単に実装できると思いますが、前者はWindowsには
無く、後者は単一プロセス内の同期として用いるのは効率が悪そうです。

Windowsは、VistaではなくXPを使っています。よろしくおねがいします。
450デフォルトの名無しさん:2008/01/26(土) 23:22:41
何でもマルチスレッドにしたがるバカw
451デフォルトの名無しさん:2008/01/26(土) 23:32:11
>>449
XPには条件変数は無いから。自分で作る。
452デフォルトの名無しさん:2008/01/27(日) 00:24:29
条件変数って何があれば自作できるんだっけ?
453デフォルトの名無しさん:2008/01/27(日) 00:30:14
Mutex/CriticalSectionとEventと変数でいいんじゃねーの?
454デフォルトの名無しさん:2008/01/27(日) 00:40:01
>>453
おそらくその組み合わせでは条件変数もどきは作れないと思うのだが・・。
でも、もし大丈夫だとされている実装とか、MS推奨の実装を知っていたら教えて。
455デフォルトの名無しさん:2008/01/27(日) 01:00:10
できないと思う理由を書いてくれ。

なんか、条件変数に過大な期待をしてるみたいだから。
456デフォルトの名無しさん:2008/01/27(日) 01:10:01
broadcast考えなきゃ、Auto Reset Eventを
SignalObjectAndWaitで待てば済む話じゃね?
457デフォルトの名無しさん:2008/01/27(日) 01:23:45
>>455
Mutexの開放とEvent待ちをアトミックに行うことができないから。

たとえばここ http://docs.sun.com/app/docs/doc/819-0390/6n2qp46ef?a=view
の一番下にあるようなコードの、pthread_mutexをCriticalSectionに置き換えて、
pthread_condを自動リセットのEventに置き換えたとすると、

バッファが空の状態で、スレッドAがデータを取り出そうとする
Event待ちの寸前でコンテキストスイッチ
まだバッファが空の状態で、スレッドBがデータを取り出そうとする
Event待ちの寸前でコンテキストスイッチ
スレッドCがデータを投入
スレッドCがSetEvent
スレッドCが再度データを投入
スレッドCがSetEvent
スレッドAがイベント待ちに入り、すぐ戻る
スレッドAがデータ取り出し完了
スレッドBがイベント待ちに入る。データがあるのにイベント待ちから戻れない

となる恐れがない? (CSのEnter/Leaveは省きました)

http://www.linux.or.jp/JM/html/glibc-linuxthreads/man3/pthread_cond_destroy.3.html の、
> 条件変数はいつでも mutex と結びつけられていなければならない。これは、あるスレッドが条件変数を
> 待とうとしている時に、他のスレッドが、先のスレッドが実際に条件変数に対して待機するその直前に
> 条件を送信する、という競合条件を避けるためである。
を参考にしました。
458デフォルトの名無しさん:2008/01/27(日) 01:30:15
というわけで、producer-consumerのうまいコード例があればお願いします。
459デフォルトの名無しさん:2008/01/27(日) 01:31:34
投入データの個数をセマフォで管理しとけばいいんじゃないかな
データ投入後→セマフォを1上げる
データ取り出し前→セマフォを1下げる(データがない=セマフォが0の場合は投入される=1以上になるまでブロック)
460デフォルトの名無しさん:2008/01/27(日) 01:35:29
>Mutexの開放とEvent待ちをアトミックに行うことができないから。
はいはい。SignalObjectAndWait, SignalObjectAndWait。
461デフォルトの名無しさん:2008/01/27(日) 01:39:35
>>460
んー、この用途に使えるのか。サンクス。調べてみます。

>>459
最悪それでいこうとおもってます。けど460のでいけるならそれがベター。
462デフォルトの名無しさん:2008/01/27(日) 01:40:44
というか、Producer-Consumerなら、スレッドプールつかって
あとは知らぬの半兵衛を決め込めばいいような気がしてきたぞ。
Producer() {
{
CriticalSectionLock csl(cs);
return if list.full?
list.push( somethings )
QueueUserWorkItem( Consumer );
}
}
Consumer(){
{ CriticalSectionLock csl(cs);
workitem = pop();
QueueUserWorkItem(Producer);
}
SomeWork;
}
463デフォルトの名無しさん:2008/01/27(日) 01:41:59
>>462
そういうのもあるんですか。そっちも調べてみます。
ありがと。
464デフォルトの名無しさん:2008/01/27(日) 01:57:33
>>456
ブロードキャストしたい場合は
465デフォルトの名無しさん:2008/01/27(日) 02:08:57
その場合は、根本から考え直しだよね。
APRみたいに、Manual Rese Eventを待つたびに、待ちスレッド変数をインクリメントして
起こされるとデクリメント。自分が最後に起こされたスレッドかどうかを判断して、
ResetEvent発行するとかさ。
466デフォルトの名無しさん:2008/01/27(日) 02:11:42
manual resetにするわけか。めんどくさいね。
467デフォルトの名無しさん:2008/01/27(日) 14:51:01
結論:Windowsはクソ
468デフォルトの名無しさん:2008/01/27(日) 15:00:27
条件変数を作るとして、それに使うWindowsの同期オブジェクトはどれが軽くてお勧めか?
469デフォルトの名無しさん:2008/01/27(日) 15:18:26
CriticalSectionにSignalObjectAndWaitできるの?
470デフォルトの名無しさん:2008/01/27(日) 15:18:47
>>468
Vistaを使う
471デフォルトの名無しさん:2008/01/27(日) 16:59:39
>>435
thread pool化した。8thread上げといてそれを、
pthread_cond_wait/signal/broadcast
pthreaf_mutex_lock/unlock
で、ぶん回した。
non thread時の倍ほどがのスピードが、漸くでた。

単純にctreate/joinだけだと、メチャメチャコストが高いのですね。
このときは、non thraed時の8倍ほど時間がかかった。

472デフォルトの名無しさん:2008/01/27(日) 18:19:52
>>468-469
CSが使えないんだとしたらエラく遅くなるよな。
実際のところどうなのか教えてエロい人。
473472:2008/01/27(日) 18:24:54
http://www.cs.wustl.edu/~schmidt/win32-cv-1.html の3章に実装例があった。
どれも大変な事になっているな。たぶん、pthread_cond_broadcast()を実現しようとしているからだと思うが。
474デフォルトの名無しさん:2008/01/27(日) 20:08:28
VS2005、C++でWin32ウィンドウプログラムを作成しています。
キューの中身が空の間、スレッドを待機させたいのですが、while(que.empty())
{
Sleep(0);
}
とすると、CPUはぶんまわされるわ、スレッド終了フラグも受け取れないわで困っています。
キューにデータが入った瞬間にスレッドが回りはじめ、かつ終了フラグも受け取るためにはどうすればよいのでしょうか?
初歩的な質問ですみませんがよろしくお願いします。
475デフォルトの名無しさん:2008/01/27(日) 20:29:07
釣り?
476デフォルトの名無しさん:2008/01/27(日) 22:12:47
いえ、釣りではないのですが…
もう少し調べてみます。
それでも分からなければ初心者スレに行きます。
スレ汚し失礼しました
477デフォルトの名無しさん:2008/01/27(日) 22:51:27
とりあえず、セマフォを使ってみよう。
478デフォルトの名無しさん:2008/01/27(日) 22:54:49
というか、今までの話題がまさにそのProducer/Consumerパターンについてなわけだが
479デフォルトの名無しさん:2008/01/28(月) 00:08:21
480デフォルトの名無しさん:2008/01/28(月) 00:09:22
>>479
C++でXPなんです・・
481デフォルトの名無しさん:2008/01/28(月) 01:08:54
つうか、セマフォ使えや、カス
482デフォルトの名無しさん:2008/01/28(月) 01:20:54
メータードセクションだろ普通
483デフォルトの名無しさん:2008/01/28(月) 01:21:26
>>481
誰にいってんの?
484デフォルトの名無しさん:2008/01/28(月) 01:23:40
>>482
へぇ。そんなのあるんだ。プロセス間でも使えて、一定回数はカーネルに落ちないでspin?
485デフォルトの名無しさん:2008/01/28(月) 02:31:00
全部ホシュするなら、全部ヤッパ明渡せヤゴラ、でOK
486デフォルトの名無しさん:2008/01/28(月) 07:52:58
?
487デフォルトの名無しさん:2008/01/28(月) 09:51:29
VMwareでLinux上げてpthread使えば解決
488デフォルトの名無しさん:2008/01/28(月) 10:42:06
queueに要素があるかは、>>477,>>481の通りセマフォでやればいいんじゃない?
増減するリソースを管理するんだからちょうどいいでしょ。
フラグの変更はイベントにでもして一緒に待つか、queueに終了って言うなにかを投げ込めば?
489デフォルトの名無しさん:2008/01/28(月) 18:01:56
Linux野郎なんでWindowsには全く疎い俺参上!

Windowsの独自スレッドだけでpthreadはないの?

あと、pthreadとWindowsスレッドを比較した利点・欠点
がまとめてあるHPとないでしょうか?
490デフォルトの名無しさん:2008/01/28(月) 20:46:19
>>484
スピンで待たせるなら、プロセス内専用だけどWindowにもInitializeCriticalSectionAndSpinCountなんてものもあるよ。
491デフォルトの名無しさん:2008/01/28(月) 22:07:07
メータードセクションは、Windowsの話だけど・・・
492デフォルトの名無しさん:2008/01/29(火) 06:27:19
CriticalSectionがspinなのはわかってるよ
493デフォルトの名無しさん:2008/01/29(火) 06:34:26
>>489
Linuxにも疎そうだな
494デフォルトの名無しさん:2008/01/29(火) 09:57:59
どうしてもpthreadがいいなら、pthreads for Win32があるでしょ。
以前mingwでつかってたよ。VCでも使えたはず。
495デフォルトの名無しさん:2008/01/29(火) 12:58:59
下のようなクラスを作って、Monitorでのロックと比較してみた。
EnterWithContextSwitchで、ロックがほとんどかち合わないで誤差の範囲で軽く、ロックが頻繁な場合だと
明らかに遅くなる。Enterは確実に遅い。

class SpinLock {
volatile int _isEntered;
public void Enter() { while (Interlocked.CompareExchange(ref _isEntered, 1, 0) != 0) { }}
public void EnterWithContextSwitch() {while (Interlocked.CompareExchange(ref _isEntered, 1, 0) != 0) {Thread.Sleep(0);}}
public void Exit() {_isEntered = 0;}
}
//試したのはこんな感じ 各スレッドで
for (int i = 0; i < _loopCount; i++) {
thp.LockDeleg(thp);//ここでLockして
DoWork(_jobTime);//ここで指定時間処理して
thp.UnLockDeleg(thp);//ここでUnlock
}
対象のロックはmontor,SpinLockともども複数生成して、ロックするときにランダムでロック対象を決めるようにした。生成するロック数も多い場合、少ない場合色々試してみた。

環境はXP Sp2 C# .NET2.0 DualCoreのアスロン何たら。
テスト中はCPUを使い切る場合もあれば各CPUが70%ぐらいで推移する場合もあり。どちらのロックでそうなるかは不明。多分SpinLock。
参考URL
http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/

何か間違ってる?ついでにおまいらのマルチスレッドに関する考え方、使い方を教えてくれ。
教えてエロイ人
496デフォルトの名無しさん:2008/01/29(火) 18:13:34
何がしたいのこれ?
497デフォルトの名無しさん:2008/01/29(火) 18:26:19
.netのモニターオブジェクトと自前スピンロックの性能評価?
498デフォルトの名無しさん:2008/01/29(火) 18:42:28
具体的に何を計りたいのかよくわからん。

ついでについては、ロックがかち合う可能性を下げるように設計する。
499495:2008/01/29(火) 18:54:29
違う回線よりすいません。
説明不足で申し訳ないです。
言われるとおり、自作スピンロックでどれだけロックが軽くなるかの調査です。
いくつかの記事で、SpinLockでのcpu消費の方が、コンテキスとスイッチより軽いと言っていたので試してみました。
結果が記事と逆になってしまったので自分のコードが何かおかしかったのかと。
500デフォルトの名無しさん:2008/01/29(火) 19:10:11
スピンロックはマルチプロセッサじゃないと効果無いんじゃないか?
スピンしてる間にロックが外れれば、カーネルに落ちなくて済むじゃん
501デフォルトの名無しさん:2008/01/29(火) 19:27:06
>環境はXP Sp2 C# .NET2.0 DualCoreのアスロン何たら。
って書いてあるから、2つあるんでそ。
502デフォルトの名無しさん:2008/01/29(火) 19:31:05
あ、ほんとだ。失敬失敬。
503デフォルトの名無しさん:2008/01/29(火) 19:33:43
単純なサンプルで重い、軽い、と早い、遅いを同列に語っても意味無いかと。

あとSleep(0)の分解能なんてろくに無いんだから
いちいちロックされてるたびに呼んでたら無駄に待たされる。
ただ、一般的には、他の誰かが処理してるからCPU時間を明け渡してあげることで
いち早くロックを取得できる可能性をあげる意味でSleepを使う

Sleep(0)の分解能調べて見て、中のジョブがどれぐらい時間かかってるか
調べて見れば、あなたのいう軽いとか遅いとかがより深く理解できると思う。

Win32だったらCriticalSectionで一発だったんだが
.netはLockかInterlockしか無いのかな
504デフォルトの名無しさん:2008/01/29(火) 19:33:52
public void EnterWithContextSwitch() {while (Interlocked.CompareExchange(ref _isEntered, 1, 0) != 0) {Thread.Sleep(0);}}
というか、これ "Sleep(0)" が原因でねーの。他にするタスクがないとき、CPU休まないじゃん。
505デフォルトの名無しさん:2008/01/29(火) 21:06:30
.NETのロックは元々クリティカルセクションだよ。
506デフォルトの名無しさん:2008/01/29(火) 21:15:59
単純なスピンロックなんざそもそも間の処理が極めて短時間で
競合なんてまず滅多に起こらん場合にしか向かん。
507デフォルトの名無しさん:2008/01/29(火) 21:27:30
どうもインタロック操作が極端に軽いと勘違いしてる奴や記事が多いな。
.NETなんて単純にロックでもそう大差はないのに。
508デフォルトの名無しさん:2008/01/29(火) 21:39:37
ああこれは件のMSDNの記事の事じゃないので念のため。
509495:2008/01/29(火) 21:59:01
>>506
そのようだ。
>>507
極端に軽いと勘違いしてた。

今は反省している
510デフォルトの名無しさん:2008/01/30(水) 13:04:30
>>21によれば、.netの機能をそのまま使えば良いんじゃないか?
511デフォルトの名無しさん:2008/01/30(水) 19:09:40
うんそう。
あえてスピンロックにするのはインタロック操作1回分までも節約したいとき。
2回→1回
512デフォルトの名無しさん:2008/02/03(日) 11:08:05
環境visualstudio2005 vc++
_beginthreadexを使ってメインを合わせて合計3個と100ms毎の割り込みをさせてるんですが、
assert(0)が有効にならない場合があります。マルチスレッドで緊急にプログラムを停止させたい場合は
どうすればいいんでしょうか?
513デフォルトの名無しさん:2008/02/03(日) 11:18:51
ExitProcess
514デフォルトの名無しさん:2008/02/03(日) 11:33:51
>>512
WaitoForSingleObjectとSetEventを使う。
515デフォルトの名無しさん:2008/02/03(日) 12:06:49
assert(0)
516デフォルトの名無しさん:2008/02/03(日) 17:58:20
>>514
Waito ?
517デフォルトの名無しさん:2008/02/03(日) 18:28:11
WaitoSinguruObujecuto と SinguruIvento
518SettoIvento ならわかるが...:2008/02/03(日) 21:12:20
SinguruIvento ?
519514:2008/02/03(日) 21:19:11
ゆるしてっ!!
520デフォルトの名無しさん:2008/02/04(月) 19:47:15
>>512
俺を使え。全力でとめてやるぜ
521デフォルトの名無しさん:2008/02/08(金) 14:49:26
生成したスレッドから、
ウィンドウハンドルを使用するマクロを使うためにはどうすればいいですかね?
522デフォルトの名無しさん:2008/02/08(金) 14:54:37
わかりやすい日本語でお願いします。
523デフォルトの名無しさん:2008/02/08(金) 18:17:55
>>521
ウインドウハンドルが欲しいのかな?
524デフォルトの名無しさん:2008/02/11(月) 23:34:04
Visual Studio.NET 2003で、Win32API、C++のプログラムをしてるんですが、
複数スレッド同時に、クラスのオブジェクトをnewしまくると、

・HEAP[aaa.exe]: HEAP: Free Heap block 3c04d0 modified at 3c04e0 after it was freed
・0xC0000005: 場所 0xfeeefeee に書き込み中にアクセス違反が発生しました。 。
・0xC0000005: 場所 0xfeeefeee を読み込み中にアクセス違反が発生しました。 。

などのエラーがでます。
何か回避方法はないでしょうか?

newしてるのは同じクラスのオブジェクトですが、
static変数は持っておらず、グローバル変数も共用してません。
共用のものとしてはstatic関数を持ってますが、使ってはいません。
525デフォルトの名無しさん:2008/02/12(火) 00:22:37
> 何か回避方法はないでしょうか?

バグを直す。
526デフォルトの名無しさん:2008/02/12(火) 00:41:03
ランタイムがシングルスレッド用になってんじゃね?
527524:2008/02/12(火) 00:58:26
>>525
シンプルな以下のクラスでテストしてみたんですが、
やっぱり同じエラーが出ます。

class TestClass{
public:
TestClass();
virtual ~TestClass();
};
TestClass::TestClass(){}
TestClass::~TestClass(){}

>>526
ランタイムってなんでしょうか?
VCで設定するものですか?それとも実行する環境に依存するもの?
528デフォルトの名無しさん:2008/02/12(火) 01:01:02
クラスの定義よりも寧ろ、「newしまくる」方を晒せよ。
529524:2008/02/12(火) 01:06:18
>>526
ありがとうございます!

VCの設定で、
プロジェクトのプロパティ→C/C++→ランタイムライブラリを、
マルチスレッドデバッグにしたらエラーが出なくなりました。
530デフォルトの名無しさん:2008/02/12(火) 01:11:48
ヤレヤレ
531デフォルトの名無しさん:2008/02/12(火) 12:34:51
>>529
シングルスレッド用でコンパイルが通ったてことはCreatThreadを使ってるのかな?_beginthreadExを使ったほうがいいよ。
532524:2008/02/13(水) 02:11:46
>>531
_beginthreadExは知りませんでした。
調べてみます。ありがとう。
533デフォルトの名無しさん:2008/02/13(水) 10:20:00
グローバル変数使う標準Cライブラリ(strtokとか)を使う場合、_beginthreadExじゃないとまずいことになる。
そうじゃないならCreateThreadでも特に問題なかったと思う。
534デフォルトの名無しさん:2008/02/13(水) 23:11:17
>>533
mallocやnewとか、VCランタイムのいろんなものがやばい。
コンパイラベンダでも無い限り、CreateThread使う必要なし。
535デフォルトの名無しさん:2008/02/14(木) 00:54:08
マルチプロセッサ環境でストアバッファのデータを反映させたい場合
pthreadだとmutex使えばいいんでしょうか?
536デフォルトの名無しさん:2008/02/14(木) 01:38:26
>>535
同期プリミティブの使用でフラッシュしてくれなかったら、どうにもならない。
537デフォルトの名無しさん:2008/02/14(木) 02:08:24
>>535
んー、volatileかな。
538デフォルトの名無しさん:2008/02/14(木) 13:03:57
メモリバリア
539535:2008/02/14(木) 23:26:30
恥のかきついでに。。。
フラッシュされるということはmutexのアンロック後に
他のスレッドから同期プリミティブを使用せずにメモリを参照しても
mutexがアンロックされた時点までの操作は完了してると見なしていい
この解釈は合ってるのかな
540デフォルトの名無しさん:2008/02/15(金) 01:55:14
posixがそれを要求してる、って
http://d.hatena.ne.jp/yupo5656/20040618/p2
ここらへんに書いてあった。
541535:2008/02/15(金) 02:19:14
なるほど。
http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap04.html#tag_04
ここにある関数を呼び出した時点でメモリが同期されるわけですね
ありがとうございました
542デフォルトの名無しさん:2008/02/15(金) 11:02:56
>>539
mutexのアンロックで書き込み側プロセッサのキャッシュがメモリと同期されても、
それだけでは読み込み側プロセッサのキャッシュはメモリと同期されないのでは?
読み込み側にも同期プリミティブ(具体的にはmutexのロック)が必要なはず
543535:2008/02/16(土) 15:34:51
>>540の"同時アクセスさえ防いでおけばすべてうまく行く"
というのを信用したんですが・・・どっちが正しい?
544デフォルトの名無しさん:2008/02/16(土) 16:21:03
キャッシュと同期オブジェクトは別じゃないのか。
545デフォルトの名無しさん:2008/02/16(土) 16:21:28
同時アクセスを防ぐ=読み側もmutexなりでロックしにいく

でも読み込みだけならロックいらないよね。volatile最強!
546デフォルトの名無しさん:2008/02/16(土) 16:39:51
>>545
一応マジレスしておくと、volatileでは確実に読めることが保証されない。安全を期するならロックした方が楽。
# 理由については割愛。
547デフォルトの名無しさん:2008/02/16(土) 17:41:24
CPUのマニュアル読むのが一番
548デフォルトの名無しさん:2008/02/16(土) 17:42:24
>>543
読み込み側もmutexをロックしないと、同時アクセスを防げないじゃないか。
まだ書き込み側がmutexをアンロックする前かもしれないのに。
549デフォルトの名無しさん:2008/02/17(日) 15:13:07
pthreadの、pthread_join()とsleep()の関係について質問します。

主系スレッドZにて、子スレッドa, b, cをpthread_create()により作成します。子スレッドa, b, cは一定時間経過後に処理を行います。一定時間経過するのを待機する場合、sleep()を使っています。

主系スレッドZでは、子スレッドa, b, cが終了するのを待つために、pthread_join()を使っています。しかし、子スレッドa, b, cがsleep()で待機しているときを、子スレッドが終了した時と勘違いしているようです。

現在では、子スレッドa, b, cが終了する前に、それぞれが主系スレッドZにsignalを送るようにしています。主系スレッドZでは、signalが来るまで待機としています。

最初にやっていた、pthread_join(), sleep()の組合せの方がスマートだと思うのですが、こちらの方法でうまくやるのは無理なのでしょうか?
環境を書き忘れていました。

【OS】debian/etch

【言語】C(pthread/posix)

【実行環境】
glibc2.3.6
gcc4.1.2
kernel 2.6.18-6-486
libpthread NPTL2.3.6
551デフォルトの名無しさん:2008/02/17(日) 15:21:59
突起フイタ
552デフォルトの名無しさん:2008/02/17(日) 15:50:00
>主系スレッドZでは、子スレッドa, b, cが終了するのを待つために、
>pthread_join()を使っています。しかし、子スレッドa, b, cがsleep()で待機しているときを、子スレッドが終了した時と勘違いしているようです。

コード晒してみてくれ
553549:2008/02/17(日) 16:23:25
どうやら勘違いだったようです。

真の原因は、Zでログファイル用に
fp_glb=fopen("Z.log","w");
として、fpを持っているのですが、子スレッドが、
fprintf(fp_glb, "log write thread name [a]\n");
として、共通のログファイルに書き込みを行おうすると、死んでいるようでした。子スレッドでは、書き込む前に排他ロックを行っているのですが、主系スレッドでは行っていないことが原因だと思っています。
554デフォルトの名無しさん:2008/02/17(日) 16:24:12
無茶苦茶だな。
555デフォルトの名無しさん:2008/02/19(火) 09:12:29
VC++にpthreadはないのでしょうか?
556デフォルトの名無しさん:2008/02/19(火) 11:47:28
557デフォルトの名無しさん:2008/02/20(水) 19:33:15
自分から終了することもあるし、外部から終了通知を受け取ることもある
ようなスレッド関数について質問です。
こういう場合、(スレッド関数はすでに終了してるぞ!)フラグや
(外部から終了通知が出されたぞ!)的な何かはいったいどうやって実装していますか?
自分はいつも

bool isActive = false;
bool IsThreadActive() { lock {return isActive} }
void SetThreadActive(bool flag) { lock {isActive = flag; } }
void ThreadFunc() {
 SetThreadActive(true);
 try {
  while (IsThreadActive()) {
   ... いろんな処理
  }
 } catch(...) {
  SetThreadActive(false);
  throw;
 }
}

的なやり方でやってしまっているのですが、
これって正しいのでしょうか?
また、もしあればもっといい方法を教えていただけると助かります。
558557:2008/02/20(水) 19:36:19
書き忘れました
while (IsThreadActive()) {
 ... いろんな処理
}
の内部から breakで抜けることもあります。
(SetThreadActive(false)も付け足してください)
559デフォルトの名無しさん:2008/02/20(水) 19:41:56
終了要求フラグとすでに終了してるぞフラグは別にした方がいいんじゃないかな
すでに終了してるぞフラグが要るかどうか(何に使うのか)にもよるような
560デフォルトの名無しさん:2008/02/20(水) 20:03:24
スレッドでいくつかの処理を行いたいのですが、
その処理の内容が
1、実はまったくスレッドが必要にならない場合がある
2、処理の行われる間隔が長いので、
  続く処理が無いようならとりあえずスレッドを終了させたい
というもので、ある処理のリクエストが入ったとき、

*スレッドが稼動していればそのままリクエストを追加
*稼動していなければ新たにスレッドを起動して処理を開始
*終了要求が入ったらすべてのリクエストを破棄&スレッドを終了

ということがしたいのです。
561デフォルトの名無しさん:2008/02/20(水) 20:13:33
スレッドを終了する要因がメイン側からの要求だけなら、
スレッドが生きてるかどうかはメイン側が完全に把握してるはずなので、
子スレッド側から「すでに終了してるぞ」フラグを操作する必要はないはず
562デフォルトの名無しさん:2008/02/20(水) 20:23:14
>>561
スレッドを終了させる要因には、メイン側からの通知もそうですが、
子スレッド内での例外や、自殺も含まれます。
結局、これはフラグで操作するしかないのでしょうか?
というのも、「スレッドをフラグで操るなんて危なすぎ」みたいな話を聞いたことがあるので・・・
それにconditionとか、なんとなくかっちょいい機能を使いたいような気もします
563デフォルトの名無しさん:2008/02/20(水) 20:30:57
>>561
すいません。分かりにくかったですね。これも追加してください
*リクエストが無ければ、とりあえずスレッドを終了(再びリクエストが来たら再度起動)
564デフォルトの名無しさん:2008/02/20(水) 20:55:19
例外で死ぬなら、残ったリクエストを誰かが引き継がなきゃいけないような・・・
キャッチできるなら再開して残りのリクエストを処理する方がいいんじゃないかな
リクエストキューとスレッド生存フラグは単一のロックで操作しないとまずいことになると思う
終了要求フラグは別のロックでも構わないけど、一緒にしとくのが無難かと

親側
lock {
リクエスト投入
if (スレッド生存==false) { 子スレッド起動; スレッド生存=true }
}
子側
loop {
lock {
if (終了要求) { スレッド生存=false; return }
リクエスト取り出し
if (もうリクエストないよ) { スレッド生存=false; return }
}
try { リクエスト処理 } catch { エラーメッセージを吐くとか }
}
たぶんこんな感じ?
565デフォルトの名無しさん:2008/02/20(水) 20:57:14
終了してるかどうかはそのためのもの(WinならWaitForSingleObjectとか)で調べるでしょう。
566デフォルトの名無しさん:2008/02/20(水) 21:08:10
>>565
スレッドが例外とかで突然死した場合はメイン側でWaitFor〜なりで捕まえて再起動するしかないけど、
リクエスト投入時の新スレッド起動判断をそれでやると、
その直前にリクエストがキューにないと判断したため自発的に終了しつつあるスレッドと入れ違いになる可能性が・・
567デフォルトの名無しさん:2008/02/20(水) 21:25:45
>>564
おお、なるほど。そういう風にやればいいんですね。
>>557だと、「いろいろな処理」中にisActiveがfalse、
かつリクエスト追加でフラグがtrueになるとスレッド二つになりますし、
タイミング的にスレッド消える危険もありますね。
それをテンプレにしていろいろ試してみたいと思います。
ありがとうございました。
568デフォルトの名無しさん:2008/02/20(水) 22:14:25
俺ならこんな構造にする。
・リクエストを出すスレッドはイベントループを持つ。
・作業スレッドはリクエストキューと終了要求フラグを見ながら愚直に仕事をする。
・作業スレッドが処理を1つ済ませたり終了したりしたら、
1回だけ呼ばれるコールバックを要求元スレッドのイベントループに登録する。
・コールバックは要求元スレッドで走り、処理結果やエラーを通知する。
問題は、イベント待ちで寝ているときに目を覚まさせる方法が
既成のイベントループに必ずしも用意されていないこと。
569デフォルトの名無しさん:2008/02/21(木) 09:40:13
毒を投げればいいだろ
570デフォルトの名無しさん:2008/02/21(木) 09:48:43
基本的にスレッドはブロッキング操作があるようなものを非同期で行わせるために俺は使ってるから,
イベントループとか使えないんだよね
571デフォルトの名無しさん:2008/02/21(木) 12:56:56
一方、漏れは匙を投げた。
572デフォルトの名無しさん:2008/02/21(木) 19:03:51
double pi=3.14159265358979823846;
if((fp=fopen("PI.bin","wb"))==NULL)
printf("\aファイルをオープンできません。\n");
else{
fwrite(&pi,sizeof(double),1,fp);
fclose(fp);
}

C言語で↑のようにpiをバイナリファイルに書き込んで、
BZというバイナリエディタで開いたのですが”$-DT・ @”(文字部)と表示されました。
その後にfread関数でPI.binの内容をプログラム上で出力すると3.1415926……とさきほどの数字に限りなく近い数字できちんと表示されたのですが
バイナリエディタで見ると変な文字に変わってしまうのは、何が原因なのでしょうか?これをバイナリファイルとして正しく見れる方法はあるのでしょうか。
573デフォルトの名無しさん:2008/02/21(木) 19:04:04
ブルータス!お前もか!
574デフォルトの名無しさん:2008/02/21(木) 19:07:45
>>572
スレタイと何か関係あった?
575デフォルトの名無しさん:2008/02/21(木) 19:10:06
>>574
完全に誤爆です
すいませんでしt
576デフォルトの名無しさん:2008/02/26(火) 01:43:14
>>572
原因はお前の頭が悪いこと。
そもそもスレ違い。
577デフォルトの名無しさん:2008/02/26(火) 04:30:54
5日も前に誤爆だったと謝罪済みのレスに文句言う馬鹿って一体何考えてるの?
578デフォルトの名無しさん:2008/02/26(火) 10:36:12
脊髄で書いてるのだろう
579デフォルトの名無しさん:2008/02/27(水) 17:15:56
脊髄電脳化w
580デフォルトの名無しさん:2008/02/28(木) 00:56:57
マルチスレッド対応の
ハッシュリストのソースコードとかある?
581デフォルトの名無しさん:2008/02/28(木) 12:32:38
ハッシュは速いのが売りなんだから、まるごとクリティカルセクションで包んでおけ
582デフォルトの名無しさん:2008/02/28(木) 12:51:50
>>580
Javaのjava.util.concurrent.ConcurrentHashMap
583デフォルトの名無しさん:2008/02/28(木) 13:19:30
javaならHighly Scalable JavaのNonBlockingHashMap等
ttp://sourceforge.net/projects/high-scale-lib
584デフォルトの名無しさん:2008/02/28(木) 16:02:03
>>581
意味ねーw
585デフォルトの名無しさん:2008/02/29(金) 23:39:30
同期処理なんてしなくてよし。
すべては運任せ。
マルチスレッドの邪神様に任せておきなさい。
586デフォルトの名無しさん:2008/03/03(月) 11:34:48
コア1個ならなんとかなるさ、きっと
587デフォルトの名無しさん:2008/03/03(月) 21:36:55
●5 コアは一個だが、HTだった
588デフォルトの名無しさん:2008/03/03(月) 23:09:15
HTといえば、マルチコアの場合は異なるコア同士が同じキャッシュラインに
アクセスしない方がいいけど、HTの場合は逆になるの?
589デフォルトの名無しさん:2008/03/03(月) 23:49:44
マルチプロセッサ・マルチコア・HTで論理CPUが8個とかってどこのXEONだっけ?
590デフォルトの名無しさん:2008/03/04(火) 16:41:04
AMDのです
591デフォルトの名無しさん:2008/03/04(火) 22:30:10
>>588
キャッシュが共有の場合は、キャッシュラインが同じでもOK。そのほうが効率よい。
キャッシュが分かれている場合は、同じキャッシュラインへの書き込みは最悪になる。MESIプロトコルで具具ってみよう。
592デフォルトの名無しさん:2008/03/05(水) 13:50:16
593デフォルトの名無しさん:2008/03/05(水) 14:19:28
トランザクションメモリって、
JavaのAtomicReference#compareAndSetみたいなのじゃだめなの?
594デフォルトの名無しさん:2008/03/05(水) 16:58:48
失敗したとき、その中でやったことは全部無しにしてくれるんだろうか?
>>593 良い場合もあるけど、例えば、複数のHashMapとかをatomicに操作したい場合は面倒じゃない?
595デフォルトの名無しさん:2008/03/05(水) 23:18:48
マルチスレッドなくなってしまう。
今までがずっとCPUだと思っていたものは、実はスレッドなんで、。
596デフォルトの名無しさん:2008/03/06(木) 02:46:25
Windowsでの条件変数実装の話題蒸し返したいので、俺の調査結果を晒してみる。

apr -> 再帰mutex非サポートぽい?簡潔過ぎるし、他にもバグあるだろ絶対。
yaneSDK3rd::LockObject -> すごく分かりやすい実装。再帰ロックしてのwaitにバグあり。修正は簡単。
boost::condition -> 複雑。完璧なのか?タイムアウト監視にシステム時刻使ってるのが嫌。

自前のC++ライブラリ構築して使ってるが、
yaneSDK3rdベースの実装からboostベースに交換してみようと思って
とりあえず、boost::xtime使ってる部分はGetTickCountに変えた。
システム時刻は某通信プロトコルでいつでも変更されてしまうので。
っつーか、clock()とかにもFILETIME使ってるのってどうなのよ・・・
boost実装に>>473のような問題が無いか検証しようとしてるが、
こいつのアルゴリズムは結構複雑で手強そうだ・・・
肝心のACEのソースはまだ読んでない。
597デフォルトの名無しさん:2008/03/07(金) 02:19:24
条件変数の用途って
生産者/消費者的な使い方がかなりの部分を占めると思うんだけど、違うかな?
そういう用途のみに限れば、IOCP使えば充分なんじゃないのかね。
キューにデータがあるときはカーネルに行かないって言明されてるし。
598デフォルトの名無しさん:2008/03/08(土) 02:15:16
無知を承知で聞くけど、ユーザーモードに限って言えば
普通はCriticalSection一択じゃないの?
CriticalSection自体がSpinCountの設定次第でカーネルモードにいかないようになってるから
そのチューニングで大体の用途には間に合うと思うんだが。

VistaだとRead/Writeロックが実装されたから、そっち使ったほうが早いかもしれんけど。
599デフォルトの名無しさん:2008/03/08(土) 18:32:59
Windowsはあまり知らないんだけど、Enter/Leaveしか出来ないの?
600デフォルトの名無しさん:2008/03/08(土) 19:25:08
TryLock もバージョンが↓でなければできる
601デフォルトの名無しさん:2008/03/16(日) 09:31:31
VC++Windowsアプリの質問です。
メッセージループを1つのスレッドに隔離しようと思うのですが、
PostQuitMessage(0)を別スレッドから単純に呼び出しても安全でしょうか?

HWND g_hWnd
BOOL g_Active;

// g_Activeをクリティカルセクション内でやり取り
BOOL fGetActive();
VOID fSetActive(BOOL isActive);

INT WINAPI WinMain(...){
fSetActive(TRUE);
g_hWnd = (ウインドウハンドル作成);
メッセージループ用スレッド生成
while( fGetActive() ){
if(...) PostQuitMessage(0);
}
メッセージループ用スレッド後処理
return 0;
}
UINT WINAPI MessageLoop(...){
MSG msg;
msg.hwnd = g_hWnd;
while (GetMessage(&msg, NULL, 0, 0) > 0){
...
}
fSetActive(FALSE);
return 0;
}
602デフォルトの名無しさん:2008/03/16(日) 11:40:27
サブスレッドからアプリケーションを直接終了させる設計は変じゃないか。
メインスレッドに何らかのメッセージを送って、メインスレッドからアプリケーションを終了すればよいじゃない。
面倒なら、少々強引だが、PostThreadMessageでメインスレッドに
直接WM_QUITを送りつけるのも。あまりお勧めしないが。
603デフォルトの名無しさん:2008/03/16(日) 12:57:27
ウィンドウはそれを作ったスレッドに結びついているよ
604デフォルトの名無しさん:2008/03/16(日) 13:10:12
>>601
PostQuitMessageを別スレッドから呼び出すことは問題ないけど、
メッセージは、ウィンドウの作成元のスレッドにしか来ないよ
別スレッドでGetMessageしたかったら、そっち側でCreateWindowしないとだめ
605604:2008/03/16(日) 13:11:34
>PostQuitMessageを別スレッドから呼び出すことは問題ないけど、
って、ウソでした、カレントスレッドにWM_QUITを送るだけか
PostThreadMessageで相手スレッドにWM_QUITを送ればいいかも
606デフォルトの名無しさん:2008/03/16(日) 14:31:10
>>602-605
ありがとうございます。
MSG構造体へメッセージを送る際のデッドロックが心配でした。
>>602
>サブスレッドからアプリケーションを直接終了させる設計は変じゃないか。
ウインドウモードだと×からも終了させる場合があるのと、
メインスレッドのID取得が難しそうなので変えられなそうです。
607デフォルトの名無しさん:2008/03/16(日) 22:42:23
>メインスレッドのID取得
プログラム開始時にメインスレッドから GetCurrentThreadId を呼んで、
メインスレッドのIDが取得して、それをグローバル変数にでも入れておけば良いかも。

それがいやなら、メインスレッドにくくりついている非表示ウィンドウを一つ作っておいて、
そこに向かって PostMessage して、メインスレッドにメッセージをポストするのも手。
windowsではよくある話。
608601、606:2008/03/17(月) 15:08:05
もう一つ質問させてください。
メインスレッドがウィンドウを持ち、GetMessageのループをしていてかつ、
サブスレッドがメインスレッドのウィンドウにDirect3Dで描画している場合、
GetMessageとDirect3DがHWNDへのアクセス権をもめてクラッシュしますか?
609デフォルトの名無しさん:2008/03/17(月) 16:22:56
swapchainでググれ
610デフォルトの名無しさん:2008/03/17(月) 17:00:28
サブスレッドでバックバッファに書き込んだ後、
メインスレッドにバッファを転送するべきという意味ですか?
うーん……
611デフォルトの名無しさん:2008/03/17(月) 21:18:56
>>608
クラッシュしませんよ。
ただ、例外があって、ディバイスをリセットするときだけはディバイスを作成したスレッドからリセットを
コールしてあげないといけないからその点は注意。
メインスレッドでディバイスを作成した場合は、サブスレッドからはリセットは出来ない。

なので、もし、サブスレッドからディバイスをリセットする場合は、
まず、適当な自作ウィンドウメッセージをサブスレッドからメインスレッドのウィンドウに投げて、
メインスレッドのウィンドウがそれを拾ったらメインスレッド側から
ディバイスをリセットする。
612デフォルトの名無しさん:2008/03/18(火) 21:47:01
Linux 2.6.21です
sigwait()しているスレッドに他のスレッドからpthread_cancel()を実行してもスレッドがキャンセルされません
sigwait()はキャンセルポイントのはずなのになぜ、と困惑しています
うちの環境のみなんでしょうか
もしくはLinuxの仕様?
613612:2008/03/19(水) 07:24:50
すいません、自分の勘違いでした
614デフォルトの名無しさん:2008/03/25(火) 19:48:12
すいません。教えてください。
linux 2.6.20でpthreadです。
sched_get_priority_minとsched_get_priority_maxで優先度の
最大値と最小値を得たところ両方0でした。
これは優先度を選択できないということでしょうか。
優先度の最大値、最小値を得るのに使った引数は
sched_getscheduler(getpid())で値は0でした。
よろしくおねがいします。
あ、あと書き忘れましたがlttng0.9.0のパッチを当ててます。
615デフォルトの名無しさん:2008/03/25(火) 20:06:05
>>614
http://www.linux.or.jp/JM/html/LDP_man-pages/man2/sched_get_priority_max.2.html
>Linux では SCHED_FIFO と SCHED_RR では 1 から 99 の範囲の静的プライオリティーを持ち、
>SCHED_OTHER と SCHED_BATCH ではプライオリティとして 0 を持つ。
616614:2008/03/25(火) 21:04:25
ありがとうございます。
優先度を指定しよう思ったらSCHED_FIFOかSCHED_RRにしろということですね。
考えて見ます。
617デフォルトの名無しさん:2008/03/26(水) 02:52:53
RTの付いたカーネルじゃないとダメじゃなかったっけ?
618デフォルトの名無しさん:2008/03/31(月) 00:04:13
Numaで確保した共有メモリ内に
pthread mutext仕込むと
Numaで共有しているマシン間で
排他取れるの?

619デフォルトの名無しさん:2008/03/31(月) 13:08:46
出来ないの?
620デフォルトの名無しさん:2008/03/31(月) 22:36:00
教えてくれよw
621デフォルトの名無しさん:2008/04/01(火) 07:07:46
POSIX準拠なら取れないとおかしいという結論になるはず。
「NUMAで確保したの共有メモリ」がPOSIX準拠かどうかまでは知ったこっちゃねぇ。
622デフォルトの名無しさん:2008/04/01(火) 16:27:39
もし出来ないなら、アドレス空間が共有できてもうれしくないと思うんだが。
割と普通なOpteron複数搭載機ではまる人が続出しそう。
623デフォルトの名無しさん:2008/04/09(水) 23:10:05
http://docs.sun.com/app/docs/doc/819-0390/6n2qp46ei?a=view

この関数ってなんか役に立つの?
624デフォルトの名無しさん:2008/04/10(木) 00:11:50
??


625デフォルトの名無しさん:2008/04/10(木) 00:19:17
>>623
リード側と書き込み側の間でブロックしにくくなるんじゃないかな?
626デフォルトの名無しさん:2008/04/10(木) 00:37:03
>>625
じゃあmutexでおk?
627デフォルトの名無しさん:2008/04/10(木) 05:29:38
??
628デフォルトの名無しさん:2008/04/10(木) 09:01:57
read同士でblockしない点が有用。
629デフォルトの名無しさん:2008/04/10(木) 10:00:18
あるデータAをRWロックでブロックしてるとする

スレッド1がAを読み込もうとしてるときに・・・

スレッド2がAを読み込むことがある
スレッド3がAを書き込むことがある

となっている2つの場合を考える

もしスレッド1と2のみであれば、Aの値は不変のはずだから
1が処理中でも2は処理できる。
つまりRead同士ではブロックする必要がない

しかし、1と2が処理中に3が処理しようとするとおかしくなる。
だから読み込み同士ではブロックないが
書き込みはブロックしないといけない。
これがReadロック。

逆に、3が動いているときに、1と2が読み込もうとしている場合は
3が終わるまでは1も2も読み込んではいけない。
スレッド4が書き込みをしようとしてたとして、これも当然ブロックしないといけない。
つまり排他処理するのがWriteロック。

これをMutexに置き換えると、Read同士でブロックしてしまう可能性があるので
その頻度によってパフォーマンスが落ちることが考えられる。
しかし、とりあえず動かすことが重要であれば、置き換えるだけでも動く。

630デフォルトの名無しさん:2008/04/12(土) 12:43:28
マルチスレッドで仕事量分割するための
手法説明している本ってないっすか?
631デフォルトの名無しさん:2008/04/12(土) 15:24:51
VC6でマルチスレッドのアプリ作ってるんだがトラウマになりそうだ
632デフォルトの名無しさん:2008/04/12(土) 22:27:49
マルチスレッド間で
カスタムメモリアロケタ君を
書きたいけど基本的なロジックとか
みんな何参考にしてるの?
633デフォルトの名無しさん:2008/04/13(日) 23:00:37
すみません。

デバッグ中に、CPU帯域を独占してるスレッドを特定したいのですが。
なにかいい方法はありませんか?

開発環境はVisualStudio2005で言語はVC++です。
634デフォルトの名無しさん:2008/04/14(月) 00:02:22
パフォーマンスモニタでスレッドIDごとの負荷率が出る。
スレッドIDはデバッガで一時停止のスレッドで見られる
635デフォルトの名無しさん:2008/04/14(月) 00:17:59
>>634
ありがとうございます。
特定できました。
636デフォルトの名無しさん:2008/04/18(金) 07:54:17
>>635
特定しました。
637デフォルトの名無しさん:2008/04/18(金) 14:08:38
特定しますた
638デフォルトの名無しさん:2008/04/18(金) 22:40:16
lock-freeアルゴリズムの
検証方法教えてくれよ

どうやって正当性保障するんだよw
あれ難しすぎだ
639デフォルトの名無しさん:2008/04/20(日) 18:56:56
SPINみたいなのを使うんだろうか?
640デフォルトの名無しさん:2008/04/20(日) 23:36:09
volatileで十分
641デフォルトの名無しさん:2008/04/21(月) 00:52:23
原論文に検証あるだろ?
642デフォルトの名無しさん:2008/04/21(月) 21:53:58
それが理解できないから、易しく解説して

って言う話じゃないのかな。
643デフォルトの名無しさん:2008/04/21(月) 22:43:36
数式での検証と
実装の検証は違うと思うのは俺だけw?

俺は頭が悪いんだろうなw
644デフォルトの名無しさん:2008/04/21(月) 23:37:15
うん、頭が悪い。

「プログラムの正しさの証明」って言われて、
この証明が数学で言う証明のことだと理解できないタイプ。
645デフォルトの名無しさん:2008/04/22(火) 07:35:55
実用性ない数式出されてもなぁ
後から付帯条件つきまくる数式
出されてもなぁ
646デフォルトの名無しさん:2008/04/22(火) 09:36:27
マジで頭悪そう
647デフォルトの名無しさん:2008/04/22(火) 22:16:26
ここも過疎ってるよなぁw
648デフォルトの名無しさん:2008/04/23(水) 08:00:42
一覧に無いからだと思うあげ!
649デフォルトの名無しさん:2008/05/02(金) 17:43:24
自作板にいるキチガイです。シングルスレッドで作成されてるソフトが
カーネルによってマルチコアにスレッド(タスクのことか?)が分散されると申しております。
このIDだけの発言では分かりにくいが、このスレにはシングルスレッドでもマルチコアのほうが早いと
のたまわってるキチガイがいます。
まだまだシングルCPUで頑張る人集合
http://pc11.2ch.net/test/read.cgi/jisaku/1169829748/

800 Socket774 sage New! 2008/05/02(金) 08:31:32 ID:Aaj/7HlH
このスレのシングルコアユーザーは未だにWindows3.1を使ってるようだw
801 Socket774 sage New! 2008/05/02(金) 08:32:49 ID:Aaj/7HlH
プログラムのスレッドと
CPUが処理する単位のスレッドは
意味が違うw
802 Socket774 sage New! 2008/05/02(金) 08:42:42 ID:Aaj/7HlH
プログラムのスレッドはカーネルによってさらに細分化される
与えられたCPUタイムによってそれを1つづつ実行していく
大まかに2ブロックに分割されたとしよう
1コアが1ブロックを実行してCPU使用権が終了する
その時に2コアが暇をしてるので2ブロックに即座に使用権が渡される
つまり単純に2倍の処理性能になる
806 Socket774 sage New! 2008/05/02(金) 10:52:29 ID:Aaj/7HlH
いやだからマルチスレッドOSって時点で
実際のCPU利用率は半分以下なんだよ
どんだけがんばってもそうなの
シングルコアだったら100%使えるとかないからw
コアが2になるとより100%に近い状態になるわけ
一般に1.8倍だと言われる
MS-DOSやWindows3.1を使ってる人はシングルコアのが早いかもねwww
807 Socket774 sage New! 2008/05/02(金) 10:57:04 ID:Aaj/7HlH
>>803
ベンチマークのような単純処理の繰り返しではスレッドの細分化はほとんど行われない
ゲームみたいな大きなスレッドになると実際に4倍近くの性能を発揮する
650デフォルトの名無しさん:2008/05/02(金) 17:51:33
>>649
頭のおかしな人というのはある程度の確率で常にあらわれるものであって、
そういう人がいるのはおかしいとか、説明して頭をよくしてあげよう等の考えは
全くの無駄だと思う。中身の入って無い枝豆同様ハズレとして無視するよりない。
いらいらする気持はわかるけどね。
651デフォルトの名無しさん:2008/05/02(金) 17:52:33
コピペ君に応答する奴も馬鹿だな、まで読んだ。
652デフォルトの名無しさん:2008/05/02(金) 19:14:41
osのタスク切り替え戦略によってはそうなるかもしれないけど、
普通は強制的な一定タイムスライスじゃないよね。
システムコール待つのにビジーウェイトでもしてると思ってんのか。
653デフォルトの名無しさん:2008/05/02(金) 20:14:27
ほかのタスクや割り込み処理に割り込まれる可能性が減る(ほかのCPUに割り振られる)から
「遅くなりにくい」ということはいえるが
速くなることはないだろうなあ。

って件のスレで当人書いてるじゃん
654デフォルトの名無しさん:2008/05/02(金) 21:56:31
1coreの時にOS側のタスクによるオーバヘッドが1%程度あったとすると
2coreならアプリの実行時間が1%短くなる程度なら有り得る
655デフォルトの名無しさん:2008/05/03(土) 06:58:19
ゲームでならDirectSoundは別スレッドで動いてるので
もうちょっと効果あるかもね。
656デフォルトの名無しさん:2008/05/03(土) 08:29:25
例えばX11だと描画はサーバプロセスが行なうから結構効果がありますね。
でもそれをシングルスレッドアプリが速くなると言ってしまうとちょっと違うと思いますが。
657デフォルトの名無しさん:2008/05/03(土) 08:33:56
よっぽど単純なプログラムでもない限り
完全なシングルスレッドなんてあり得ないんですけどねw
658デフォルトの名無しさん:2008/05/03(土) 08:40:56
たとえばEXCELで
再計算処理が行われてる時にメニューを実行すると
再計算、描画、メニューの3つのスレッドが形成される

659デフォルトの名無しさん:2008/05/03(土) 08:47:38
ビス太のユーザーランドスレッドの方針を分かって話してるの?
660デフォルトの名無しさん:2008/05/03(土) 12:26:31
スレッドプールのはなし?
661デフォルトの名無しさん:2008/05/03(土) 15:17:42
>>658
スレッドが生成されるかどうかと
並行実行するかどうかは別だぞ
662デフォルトの名無しさん:2008/05/03(土) 18:15:41
OpenMP中で使ってるとか
そんなんじゃねーのw
663デフォルトの名無しさん:2008/05/03(土) 19:22:28
>>661
XPでは平行実行してるが?
664デフォルトの名無しさん:2008/05/03(土) 19:59:25
>>663
させるかどうか、だ
665デフォルトの名無しさん:2008/05/03(土) 23:51:43
シングルスレッドでコンパイルするやつはいないだろw
666デフォルトの名無しさん:2008/05/04(日) 00:40:42
それまでの話の流れとは関係ないが

「マルチスレッド対応ライブラリを使用する」と
「マルチスレッドで動作するプログラムにする」は全く違うのだが
まさかとは思うが、>>665はそういう意味じゃないよな?
当然、「コンパイラをマルチスレッドで動作させる」だよね?


一応触れておくと
Win32で普通にGUIプログラムを作る場合、明示的にスレッド関連の操作をしない限り
マルチスレッドで動くことは無い。
何故なら、メッセージキューが1スレッドに1つ作られるので
そこからのイベントで処理を記述する書き方だと、1スレッドにしかならないから。
(イベントハンドラでスレッド操作をすれば当然マルチスレッドも可能)
もちろん、カーネル内の処理(割り込み等)は別。
667デフォルトの名無しさん:2008/05/04(日) 00:59:30
そういえば、Win9xのWinsock2の非同期処理は
内部的にスレッド作って擬似動作させてたんだっけ。
忘れてた。
668デフォルトの名無しさん:2008/05/04(日) 01:14:13
>>666
メッセージキューも明示的に作る(作らせる)ものであって
スレッド作成=メッセージキュー作成じゃないよ。
669デフォルトの名無しさん:2008/05/04(日) 12:10:33
> メッセージキューも明示的に作る(作らせる)ものであって

具体的にどうやって作るの?
670デフォルトの名無しさん:2008/05/04(日) 12:39:33
MSDNのPostThreadMessageの所に書いてあるな
これのことかな...

> その後、ポスト先のスレッドで、
> PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE) を呼び出し、
> このスレッド用のメッセージキューを強制的に作成します。

でもこれって、

> スレッドが Win32 のユーザー関数または GDI 関数のいずれかを最初に
> 呼び出した時点で、システムはそのスレッドのメッセージキューを作成
> します。

ってことだよね。

あまり「明示的」とは思えないんだが...。
672デフォルトの名無しさん:2008/05/04(日) 17:10:13
風が吹いたら桶屋が儲かるくらい暗黙的でなければ明示的
673デフォルトの名無しさん:2008/05/04(日) 22:53:30
いや別にメッセージループに入ったからといって
CPUを最後まで占有出来るわけじゃないのだ
途中で強制的に割り込まれる
そうすると他のループに権利が渡されるだけだな
マルチスレッドでコンパイルすると各メッセージループは完全に独立したスレッドになる
だから既存のアプリもほとんどはデュアルコアの恩恵がある
674デフォルトの名無しさん:2008/05/04(日) 23:11:24
おまえはそんなにメッセージループを作っているのか?

大多数のアプリはWinMainの中のGetMessage1つだけだと思うが
675デフォルトの名無しさん:2008/05/04(日) 23:12:03
それと、「マルチスレッドでコンパイルする」の意味を具体的に説明しろよ
676デフォルトの名無しさん:2008/05/04(日) 23:14:14
上の方は、プリエンプティブマルチタスクの解説で、4行目の
「他のループ」=「他のプロセスのメッセージループ」なのかなー
と思って読んでいたが

>マルチスレッドでコンパイルすると各メッセージループは完全に独立したスレッドになる

え?
677デフォルトの名無しさん:2008/05/05(月) 00:56:45
ちょっぴりエスパー能力を発揮して解読してみた。

普通、「メッセージループ」と言うと
while (GetMessage()) { ... } の部分のことを指すと思うのだが
おそらくこのヒトは、DispatchMessageで間接的に呼ばれるルーチン、
大抵は「WndProcの呼び出し1回」のことを
「メッセージループ」と呼んでいるような気がする。
678デフォルトの名無しさん:2008/05/05(月) 01:18:24
だとしてもウインドウプロシージャがマルチスレッドで
並列実行されたりはしないと思うが。
679デフォルトの名無しさん:2008/05/05(月) 01:48:05
もちろんその通り。

大丈夫、基本的な仕組みを理解してないのは、多分一人だけだから。
680デフォルトの名無しさん:2008/05/05(月) 03:39:24
え? そうなん?
メッセージループをマルチスレッドでコンパイルしたら
完全にプリエンプティブなマルチコアになるでしょ
681デフォルトの名無しさん:2008/05/05(月) 05:18:58
だからその「マルチスレッドでコンパイル」って、何をどうすることなの?
682デフォルトの名無しさん:2008/05/05(月) 05:34:27
一応、>>666の前半部に、候補としていくつか挙げてあるけど
・マルチスレッドライブラリを使用する(コンパイラオプションを設定)
・マルチスレッドで動作するようにソースコードを書き換えてコンパイルし直す
・コンパイル時にコンパイラがマルチスレッドで動作するオプションを使う(対応しているもののみ)
・その他


ところで、「プリエンプティブなマルチコアになる」って何?
「マルチスレッドでコンパイルする」「メッセージループがスレッドになる」に続いて
またまた第三者からは理解不能な言葉が出て来てるんですけど。
683デフォルトの名無しさん:2008/05/05(月) 05:37:36
>>680
これは釣りだろ
684デフォルトの名無しさん:2008/05/05(月) 06:45:01
「マルチスレッドでコンパイルする」

そういえばVS2005から並行コンパイルができるようになったけど
そのことかな。
685デフォルトの名無しさん:2008/05/05(月) 08:03:25
>>683
知ってる単語を並べただけと言う疑惑も捨てがたい。(w
686デフォルトの名無しさん:2008/05/05(月) 10:57:32
データを完全にシーケンシャルに
処理する必要があるのに
スレッドの接続形態が

1-N-1って場合って

どんな利点があるの?キュー作っても処理遅くなるだけじゃね?
687デフォルトの名無しさん:2008/05/05(月) 11:26:27
メッセージの元になるイベントは、システム全体に対して非同期に起こるんだよ。
おまいのアプリ上だけじゃないし、処理終了を待って定期的に起こるわけでもない。
688デフォルトの名無しさん:2008/05/05(月) 14:20:25
マルチスレッドでコンパイルする=MTsafeにするだろう
689デフォルトの名無しさん:2008/05/05(月) 15:24:34
>>686
ここの人には「完全にシーケンシャル」の意味するところがわからないから、
その形態作った奴に聞いてみればいいんじゃね。
690デフォルトの名無しさん:2008/05/05(月) 17:14:57
よくわからないけど、入力1、処理N、出力1みたいな感じだとすると、
最後の1を遊ばせないためには良いんじゃないかという気がする。
まあ何やるか次第だけど。
691デフォルトの名無しさん:2008/05/05(月) 17:16:08
>>690
でもめちゃくちゃ排他制御かからないかなぁ?
常にシーケンシャルってことは前のデータ待って
処理しないといけないってことだろうし
692デフォルトの名無しさん:2008/05/07(水) 11:17:48
コンパイラオプションのシングルとMTが具体的に何をしてるのかは知らないが
MTにした時に各イベントは完全に非同期で発生する
並列実行してるのだと思ってるのだが違うのか?
693デフォルトの名無しさん:2008/05/07(水) 11:46:10
いいえ。イベント発生は非同期ですが、受信が並列に行われる保証はありません。
# つーか、並列実行できるくらいならイベント機構はもっと簡略化できるわけで。
694デフォルトの名無しさん:2008/05/07(水) 13:47:11
>コンパイラオプションのシングルとMTが具体的に何をしてるのかは知らないが
コンパイラのヘルプ読めよ・・・
695デフォルトの名無しさん:2008/05/07(水) 17:24:03
マルチスレッドでコンパイルといえばマルチスレッド実行されるのが当然だろ
何言ってるんだか
696デフォルトの名無しさん:2008/05/07(水) 21:18:32
・マルチスレッド (対応のコンパイラ) でコンパイルといえば
 (コンパイラが) マルチスレッド実行...

・マルチスレッド (オプションをつけた状態) でコンパイルといえば
 (生成されたプログラムが) マルチスレッド実行...

日本語難しいアルネ。
697デフォルトの名無しさん:2008/05/07(水) 22:05:44
最近のコンパイラはマルチスレッドで動作するプログラムを勝手に生成してくれるの?
698デフォルトの名無しさん:2008/05/07(水) 22:07:56
MT対応ライブラリをリンクするだけじゃね
OpenMPとか一応あるけど明示的にディレクティブを書かないといけないし
699デフォルトの名無しさん:2008/05/07(水) 22:13:13
それはライブラリの使い方次第だろう。
MT-safeになるだけっていうのとはまた違うし。

なんかレベルがよく分からない抽象的な話しかないのは気のせいか。
700デフォルトの名無しさん:2008/05/07(水) 22:27:00
>>697
コンパイラ自体は何もしないけど
MFCとかのフレームワークがするんでしょ
701デフォルトの名無しさん:2008/05/07(水) 22:32:49
私はいつものようにMFCでプログラムを組んでいた
当然のごとくMTをコンパイラオプションに指定した
ある日、子ウィンドウから親ウィンドウにある関数を実行する必要性が出てきた
私はPostMessageでオリジナルのイベントを実装することを思いついた
そこには処理Aと処理Bという2つの関数が存在した
処理Bは処理Aの結果を利用するものである
処理B単体で実行する場合もあるのでこの2つは独立していた
私は当然のごとく各イベントはシーケンスに処理させるのだと思い込んでいた
メッセージA、メッセージBと順番に親ウィンドウに送信する
するとどうだろうか
プログラムは例外エラーを発生させて画面から消えるではないか
私は挙動を調べるべく調査に乗り出した
そしてついにその原因を突き止めた
この2つの処理は同時に実行されている
702デフォルトの名無しさん:2008/05/07(水) 22:42:19
非同期のPostMessageじゃなくて同期のSendMessageだったっけ、そういうのなかった?
winapiから遠ざかりすぎてワスレタ。非同期メッセージ通信なのだから、
>各イベントはシーケンスに処理させる
って前提は、キューに入れられた順番はあるけど
cpuが空いていればキューから取り出してすぐに実行されるってこと?
703デフォルトの名無しさん:2008/05/07(水) 23:01:41
内部的にSendMessage使ってる関数でデッドロックしたことがあるのでマルチスレッド怖い
704デフォルトの名無しさん:2008/05/07(水) 23:05:04
デッドロックはアナライザで一発で見つかるから楽。
問題はコンディションレースだ。
705デフォルトの名無しさん:2008/05/08(木) 09:27:46
>>701
MFCをコンパイルするときは/MLオプションを
受け付けなかったと思ったがどうだっただろう。
/MD と /MTの切り替えは問題なく出来るはず。
さらにVS2005からは/MLは廃止になっている。

一応説明しておくと
/MLはシングルスレッド用CRTライブラリのスタティックリンク
/MTはマルチスレッド用CRTライブラリのスタティックリンク
/MDはMSVCRT.DLL(版によって名称の差異あり)へのダイナミックリンク
706デフォルトの名無しさん:2008/05/08(木) 11:54:00
メッセージキューは必要に応じてスレッドごとに生成される。
自他スレッドやOSから発行されるウインドウメッセージはメッセージキューで並列化され、
メッセージループで読み出されることによってその後のウインドウプロシージャの処理は
メッセージループのスレッドで実行される。
つまりマルチなのはキューまでで後は単一のスレッドで実行される。

ただし単純にシーケンシャルに実行されるわけではない。
キューはプライオリティキューであり順番が入れ替わることがある。
ウインドウプロシージャ内でメッセージキューに関係する命令を使った場合、
現在のメッセージの処理を一旦中断し別のメッセージに実行権を譲渡することがある。
>>701はこの辺を並列で実行されたと誤認してるものと思われる。

どうしてもマルチで動作してると言い張るつもりなら、
ウインドウプロシージャにスレッドIDの変化を調べるルーティンを入れて
変化が認められるか調べるのが一番だと思う。
707デフォルトの名無しさん:2008/05/08(木) 12:34:36
>>706
2行目訂正
誤)メッセージキューで並列化され
正)メッセージキューで直列化され
708デフォルトの名無しさん:2008/05/08(木) 12:41:26
>>701
新しいスレッドを作らない限り同時に実行は無いよ。もっとよく調べてみよう。
709デフォルトの名無しさん:2008/05/08(木) 13:18:51
WndProcがマルチスレッドに動くなら
そこらじゅうMutexやらCritical Sessionだらけになる予感
もちろんVolatile論争もこのスレ的にOK
710デフォルトの名無しさん:2008/05/09(金) 15:43:52
同期コストで逆に遅くなりそうだな。
711デフォルトの名無しさん:2008/05/11(日) 21:24:19
どうせCSocketみたいな内部でPeekMessageで回してるのを見て
同時実行されてると思い込んでるだけでしょ。
712デフォルトの名無しさん:2008/05/13(火) 20:18:26
何の技術もないんですが、気になってることを質問させてください。
マルチコアプロセッサでマルチスレッドのプログラミングをする時って
スレッドを、ポンポンって作って、後はOSとかが暇にしてるコアに
仕事を割り振ってるんですか?
それとも、プログラムの側で、「この処理はお前がやれ」ってマルチコアの
特定のコアに指定して割り振るんですか?

調べてみたら、どうも前者っぽいんですが、気になって昨夜は2時間くらい
布団の中で寝れませんでした。お願いします、教えてください。
713デフォルトの名無しさん:2008/05/13(火) 20:25:47
>>712
何も指定しなければOSが自動的に割り振る。
指定すれば割り振ることができる。
だからどっちともいえる。
714デフォルトの名無しさん:2008/05/13(火) 20:31:19
>>713
ありがとう。これで今夜はゆっくり寝れる。
もうひとつ聞きたいこと出てきました。
指定する場合ってどうやるのか、キーワードだけでも
教えていただけると有り難いです。
715デフォルトの名無しさん:2008/05/13(火) 21:06:27
716デフォルトの名無しさん:2008/05/13(火) 21:15:44
>>715
あーりーがーとー。
いろんなキーワードで調べてたけど
ずっと見つからなかったものが、ようやく見つかった。
感謝します。

お邪魔しました。
717デフォルトの名無しさん:2008/05/13(火) 22:40:13
>>716
Linuxだとtasksetってコマンドで簡単に設定できるので便利。
718デフォルトの名無しさん:2008/05/13(火) 23:52:00
>>717
おぉ。寝る前に念のためにきてみたら、またいいこと知った。
ありがとねー。
719デフォルトの名無しさん:2008/05/21(水) 17:41:08
質問させて下さい。
WindowsでGUIから何らかのアクションでスレッドを起動し、
ESCキーを押下でメッセージボックスを表示して、
スレッドの実行を中止できるようにしたいと考えています。
こんな風に↓

case IDM_KEY_ESCAPE: {
 if (thread.suspend()==0) {
  if (MessageBox(hwnd, "", ""),MB_OKCANCEL)==IDOK) { thread.terminate(); }
  else { thread.resume(); }
 }
 break;
}

で、以下のようなスレッドクラスを作成しました。
(つづきます)
720719:2008/05/21(水) 17:42:31
class Thread {
 HANDLE hthread_;
 unsigned int id_;
 void run(void) { /* 具体的な処理 */ }
public:
 void start(void) { hthread_ = (HANDLE)_beginthreadex(NULL, 0, Thread::entrypoint, this, 0, &id_); }
 DWORD suspend(void) const { return SuspendThread(handle()); }
 DWORD resume(void) const { return ResumeThread(handle())); }
 static unsigned int WINAPI entrypoint(void* instance) {
  thread_t* p = static_cast<thread_t*>(instance);
  p->run();
  _endthreadex(0);
  CloseHandle(p->handle());
  p->hthread_ = 0;
  return 0;
 }
};
721719:2008/05/21(水) 17:43:00
しかし、実際に使ってみたところ、ESCキーでメッセージボックスを表示すると、
たしかにスレッドの処理は中断するのですが、
タスクマネージャを見ると中断している間も実行メモリが数KBずつ増えていくのです。
それで中断したまま(メッセージボックスを表示したまま)しばらく放っておくと、
タスクマネージャに表示された該当プロセスのスレッド数が1つ減ります。
(つまりGUI起動時のスレッド数になる)
そこでメッセージボックスのOKを選択してスレッドを終了すると、
さらにスレッド数が1つ減って、壊れた振る舞いをするという具合です。

とりあえずスレッドクラスについて質問したいのですが、
↑は変な実装ではないでしょうか?それから使い方も問題ないでしょうか?

OS:Windows Vista x64
言語:C++
環境:Visual Studio 2008
722719:2008/05/21(水) 17:46:25
すみません。>>720のthread_tはThreadの間違い、
p->handle()はp->hthread_、それからterminateメソッドが抜けていました。

void terminate(void) {
 TerminateThread(hthread_, 0);
 CloseHandle(hthread_);
 hthread_ = 0;
}

}
723デフォルトの名無しさん:2008/05/21(水) 18:09:32
TerminateThreadで終わらせたとき、run内で動的に確保されていたリソースはどうなるでしょうか。
それと、entrypoint内_endthreadex(0)の後に記述した処理は実行されないと思うのですが。
あとは知らん。
724719:2008/05/21(水) 18:18:12
>>723 どうも。_endthread(0)でスレッドを終了したら、
自動的にentrypointから抜けてしまうのでしょうか?この辺、自信ありません。
(entrypointから抜けるときに_endthreadが呼ばれるというのはMSDNに書いてありましたが…)
あとrun内でのメモリの確保は全部boost::shared_ptrを使ってるので問題ないと思います。

いずれにしてもsuspend中に問題が発生しているわけで…。
725デフォルトの名無しさん:2008/05/21(水) 18:25:16
mallocの中でsuspendしたら・・・とか思うと怖いな
何が起きても不思議ではない気がする
726デフォルトの名無しさん:2008/05/21(水) 18:50:00
>>722
TerminateThreadの説明読んだ?
こんなおっかねーAPI俺は使ったことないぞ。
強制終了に相当する処理だよ。後始末なんか何もしない。
727719:2008/05/21(水) 18:59:04
TerminateThreadが危険というのは知識としては知ってますが、
そこに至る前のSuspendThreadの時点で問題が起きているようです。
仮にメッセージボックスでキャンセルを選んで、
TerminateThreadではなくResumeThreadを呼んだ場合でも処理が壊れるのです…。
728719:2008/05/21(水) 19:03:28
>>725
スレッド内で動的にメモリを確保するのは一般的なことだと思うのですが、
その場合にSuspendThreadを呼ぶタイミングが問題になるなら、
Suspend/ResumeThreadというのはものすごく使いにくい関数な気が。
729デフォルトの名無しさん:2008/05/21(水) 19:04:04
TerminateThread()とか_endthreadex()は、
「呼ばれたらスコープを抜けてローカル変数の解体処理をして…」
なんてことは、一 切 や っ て く れ ま せ ん 。
稼動中のPCの電源を無造作に切るかのようにスレッドの処理を打ち切ってくれます。
shared_ptrのデストラクタなんか呼ばれるわけが無いので、メモリリーク必至です。

で、知っているくせに何でそんなふざけたコード書いてんの?
730719:2008/05/21(水) 19:08:11
>>729
あ、デストラクタも呼ばれないんですか。それは知りませんでした。勉強になりました。
で、なんでこういうコードを書いているかというと、
危険だというTerminateThreadを何に置き換えるかは後で考えるとして、
とりあえずSuspend/Resumeの部分を実装するために書いたコードなわけで。
731デフォルトの名無しさん:2008/05/21(水) 19:11:12
>>728
そーだよ。
例えばクリティカルセクションに入ったまま止めてしまったら、再開させるまで他のスレッド入れなくなるわけだし。

あと、これ。
http://msdn.microsoft.com/en-us/library/ms686345(VS.85).aspx
>This function is primarily designed for use by debuggers.
>It is not intended to be used for thread synchronization.
732719:2008/05/21(水) 19:19:42
>>731
なるほど。その"This function is ..."の1文でいろいろ吹っ切れた気が…。

Suspend/Resumeの機能を実装したければ、外からスレッドに何かシグナルを送って、
スレッド自らの手でSuspendする必要があるわけですね。
SuspendThreadはその部分をよきに計らってくれるものだと勘違いしていました。
どうもありがとう〜。
733デフォルトの名無しさん:2008/05/21(水) 19:32:28
まあ精進してちょ。
734デフォルトの名無しさん:2008/05/21(水) 21:23:54
ふつーはイベントを待つ。
735デフォルトの名無しさん:2008/05/25(日) 07:53:30
グローバルにスレッド管理用のフラグを用意する
スレッド起動時にこのフラグを1にセット
スレッド内で定期的にこのフラグを監視し0になったら途中で終了する
メッセージボックスでキャンセルされた時はこのフラグを0にするだけ
736デフォルトの名無しさん:2008/05/25(日) 08:00:05
マルチスレッドだとスタック領域が別になるから
グローバルで取ったフラグ用変数のポインタをスレッドに最初に渡すのだよ
737デフォルトの名無しさん:2008/05/25(日) 08:02:38
別にクラス内のローカルな変数でもいいんだけどね
その時はクラスのポインタを渡すのだよ
クラス定義を組み込むのを忘れないでね
738デフォルトの名無しさん:2008/05/25(日) 10:51:14
あとvolatileも
739デフォルトの名無しさん:2008/05/25(日) 11:47:42
c/c++のvolatileはいろいろあるから、
ちゃんとmutexなどの同期オブジェクトを使うことをすすめる。
ただwindows限定ならvolatileにメモリバリアの意味があるのだっけ?
740デフォルトの名無しさん:2008/05/25(日) 13:03:14
> c/c++のvolatileはいろいろあるから、
> ちゃんとmutexなどの同期オブジェクトを使うことをすすめる。

もしかして volatile 変数で同期とろうとか思ってる?
741デフォルトの名無しさん:2008/05/25(日) 13:08:25
荒れる予感
742デフォルトの名無しさん:2008/05/25(日) 13:10:20
>>739
メモリバリアの意味はない。
ただ、IA32はコヒーレントキャッシュだから、volatileだけでも
大して問題がないだけ。
743デフォルトの名無しさん:2008/05/25(日) 13:18:53
ていうかこのケースは知らないが

もし「ループを一周余分に回すことになっても問題ない」という
厳密な同期が必要ないものならば、volatileで済むケースはある。
そんなに多くは無いが。
744デフォルトの名無しさん:2008/05/25(日) 13:34:51
>もし「ループを一周余分に回すことになっても問題ない」という
>厳密な同期が必要ないものならば、volatileで済むケースはある。

むしろ今回のケースでは一周分余分に回すのがアウトという状況が考えにくい。
745デフォルトの名無しさん:2008/05/25(日) 14:46:29
一周分余分に回ってアウトなら最初から排他なりセマフォなり入れるしな
746719:2008/05/25(日) 16:06:04
結局↓のようなクラスにしました。今のところ問題ありません。

class Thread {
 HANDLE hthread_, hevent_; unsigned int id_; bool cancel_;
 void run(void) { while (1) { /* 具体的な処理 */ if (cancel_check()) { return; } } }
public:
 Thread(void) : hevent_(CreateEvent(NULL, TRUE, TRUE, NULL)), cancel_(false) {}
 ~Thread() { CloseHandle(hevent_); }
 void start(void) { hthread_ = (HANDLE)_beginthreadex(NULL, 0, Thread::entrypoint, this, 0, &id_); }
 void cancel(void) { cancel_ = true; SetEvent(hevent_); }
 void suspend(void) { ResetEvent(hevent_); }
 void resume(void) { SetEvent(hevent_); }
 bool cancel_check(void) {
  if (cancel_) { cancel_ = false; return true; }
  WaitForSingleObject(hevent_, INFINITE); return false;
 }
 static unsigned int WINAPI entrypoint(void* instance) {
  thread_t* p = static_cast<thread_t*>(instance);
  p->run(); CloseHandle(p->hthread_); p->hthread_ = 0;
  return 0;
 }
};
747デフォルトの名無しさん:2008/05/25(日) 16:37:42
run()内で例外投げられたらまずくね
748デフォルトの名無しさん:2008/05/26(月) 03:02:25
>>742
ダウト
749デフォルトの名無しさん:2008/05/26(月) 03:25:49
kwsk
750デフォルトの名無しさん:2008/05/26(月) 03:27:13
OoOの問題じゃないかなと思ったり。
751デフォルトの名無しさん:2008/05/26(月) 13:30:52
UOがどうしたって?
752匿名:2008/05/30(金) 15:12:16
スレッドは非常に難しいです。
スレッドを利用しないでコンカレントプログラムが容易にできます。
以下のページが参考になります。

http://www.cspjapan.org/



753デフォルトの名無しさん:2008/05/30(金) 15:57:17
ばか?
754デフォルトの名無しさん:2008/06/05(木) 15:10:05
生成したスレッドがmallocをしている最中に
SuspendThreadするとどんな問題が発生しますか?
755デフォルトの名無しさん:2008/06/05(木) 15:26:07
mallocの中で排他制御しているだろうから、他のスレッドがmallocを呼
ぶと返ってこなくなるかも。

756デフォルトの名無しさん:2008/06/05(木) 15:27:38
mallocがマルチスレッド対応版だと仮定すると、
ヒープ管理データへのアクセスの排他のために
mutexを握るタイミングがあるはず

そのタイミングでSuspendされると
ほかのスレッドがmalloc/free関連の処理をしようとして
mutex握れなくてずっと待ちに入る
newがmallocをベースにしているならnew/deleteも

はたから見るとハングアップに見える
757デフォルトの名無しさん:2008/06/05(木) 22:23:21
>739
C#のvolatileはメモリバリアの意味もあるよ。
C/C++じゃないよ。
758デフォルトの名無しさん:2008/06/05(木) 22:32:43
ふ〜ん
759デフォルトの名無しさん:2008/06/07(土) 21:41:57
MSDNのSystem.Threading.Thread.MemoryBarrierの説明が微妙でわかりづらい

>MemoryBarrier は、複数の Intel Itanium プロセッサを使用しているシステムなど、
>ウィーク メモリ オーダリングを採用したマルチプロセッサ システムでだけ使用します。

760デフォルトの名無しさん:2008/06/07(土) 23:24:59
memory orderingの知識がないだけじゃね?
strong memory orderingのx86では不要。
シングルプロセッサ(1コア)のシステムでも不要。
weak memory orderingのItaniumを複数使ったシステムでは必要。
書いてあるとおりw
memory orderingはこれでも読んどけ
ttp://www.arch.ce.hiroshima-cu.ac.jp/~kitamura/public/architecture_2003_13.pdf
x86はSPARCのTSOと、ItniumはSPARCのRMOと同じはず
761デフォルトの名無しさん:2008/06/08(日) 00:21:36
質問しようと思ったら>>746に俺が・・・
この場合だとentrypoint内でCloseHandleしてreturn完了後にendthreadex呼ばれるという
挙動であってるのかな?で、ハンドルも問題なく閉じられるのか?
762デフォルトの名無しさん:2008/06/08(日) 05:09:09
>>746は無茶苦茶だろ。
とりあえず思ったこと。
 ・startで生成したhthreadを別のスレッドでcloseするのが変。
  代入前にサブスレッドが終了したらアウチ
 ・startが2回呼び出されたときのガードは当然してるよな
 ・とりあえずcancel_はvolatileにしとけ。即座でなくても
  そのうちtrueが伝わるだろう
 ・cancelは変数で一時停止がEventだが、どちらかに統一しとけ
 ・entrypointはprivateにしとけ
 ・entrypintでrunの例外処理しないとendthreadexが呼ばれない
 ・キャストはreinterpret_cast使え
 ・サブスレッドの実行を管理するThreadとサブスレッド処理のクラスを
  どうして同じにするかな。runとcancel_checkはThreadと別クラスに分離した
  方がよいと思う
 ・_beginthreadexとCreateEventのエラーチェックしろ
 ・サブスレッドが完了したか調べる関数がほしい
あと、Threadがスコープから抜けるとrunのthisが無効になる設計は嫌いだ。
Threadのデストラクタでjoin(WaitForSingleObject(hthread_))すべきだと思う。
呼び出し側が責任を持って事前にcancelを呼び出し、それを怠ったら
不正メモリアクセスでなく永久waitになった方がマシ
763デフォルトの名無しさん:2008/06/08(日) 12:08:58
761ですが・・・俺の場合は
・コンストラクタで生成してるけどサスペンドで作成してるから、代入前に終了はないはず
・bool使ってやってます。全体的にこれらの操作はミューテックスで排他してるんですが、
 それで十分なんでしょうか?


・なってます
・なるほどやりました。
・なるほどやりました。
・実行管理がThreadクラスで、サブ処理がRunnableインタフェースを被ったクラスのrun()メソッド
 です。Thread自身もRunnableインタフェースを継承してます。(ただしrun()は空)
・失敗してたら何もしないようにしただけです・・・
・void Thread::join(DWORD timeout){
    if(tb == NULL)return;
    ::WaitForSingleObject(tb->hThread,timeout);
  } これで十分でしょうか?


764デフォルトの名無しさん:2008/06/08(日) 13:05:59
MSが言っている"アラート可能な待機状態"とはどういう状態のことですか?
765デフォルトの名無しさん:2008/06/08(日) 13:08:55
何らかのイベント?とかで待機を中断できるってことじゃね?
766デフォルトの名無しさん:2008/06/08(日) 13:11:25
746みたいな事をやるときのboost::threadの楽さと言ったら…。
767デフォルトの名無しさん:2008/06/08(日) 13:12:39
それは、普通の待機状態とアラート可能な待機状態の違いは
スレッドプロセスが__cdeclか__stdcallかの違いである
ということですか?
768デフォルトの名無しさん:2008/06/08(日) 13:24:31
違いますね。APCとか理解できません。
769デフォルトの名無しさん:2008/06/08(日) 13:55:21
>>764
重複I/Oを使うときにのイベント待機に使う。
770デフォルトの名無しさん:2008/06/08(日) 19:17:36
>764
SleepExとかWaitFor〜Exで、bAlertable=TRUEの状態で寝てるとき
771762です:2008/06/09(月) 00:32:13
>>763
> ・コンストラクタで生成してるけどサスペンドで作成
 → 論理的に正しく動くのはわかったけど、わかりづらくない?
   ハンドル作成したスレッドが(デストラクタあたりで)closeするのが自然だと思うんだが。

> ・bool使ってやってます。全体的にこれらの操作はミューテックスで排他してるんですが、
 → startの多重チェックに同期は要らない。なぜならstartは
   一つのスレッド(メイン)からしか呼び出さないのが前提だから

> Thread自身もRunnableインタフェースを継承してます
それはJava APIと同じ設計だけど、APIの設計ミスだと思う。
各クラスの役割は最低限にしようよ。
 Runnable: サブスレッドで実行する処理のクラス(主にサブスレッドで使用)
 Thread: Runnableのスレッド実行を管理するクラス(メインスレッドから使用)
実行制御でもcancel/suspend/resumeは処理固有なのでRunnable側に実装。
スレッドハンドルはスレッド実行管理の話だからThreadでclose。

> void Thread::join(DWORD timeout)
できれば戻り値をboolにして
DWORD status = ::WaitForSingleObject(?????)
if (status == WAIT_ABANDONED) throw ????;
return status == WAIT_OBJECT_0; // 完了したかどうか
かな。
772デフォルトの名無しさん:2008/06/09(月) 02:04:45
JavaのThreadにケチつけるアホがいるスレはここですか?
773デフォルトの名無しさん:2008/06/09(月) 02:17:36
JavaのThread implements Runnableは失敗だろjk
774デフォルトの名無しさん:2008/06/09(月) 18:16:32
Treadクラスの継承が失敗だろ
775デフォルトの名無しさん:2008/06/09(月) 23:04:19
761です。もう全然うまくいかないので、なんか言ってもらうために
スレッド周辺のプログラムをアップしてみます・・・。include "common.h"は消していいです
お願いします><
ttp://ccfa.info/cgi-bin/up/src/up20166.zip
776デフォルトの名無しさん:2008/06/09(月) 23:06:31
よし、何か言ってやる。
>>775 がんばれ!
777デフォルトの名無しさん:2008/06/10(火) 01:28:22
>>775
○Mutex
・LockでWaitForSingleObjectの戻り値確認しろ。タイムアウトしたら大変なことになるぞ
○Thread
・何でthread_bodyの定義を書く前に変数宣言できるんだ?コンパイル通った?
 thread_bodyのスマートポインタでないとマズくね?
・start内に例外発生するとマズい場所が多すぎ。line 60,61,62,63,64,68
・isAliveのロジックが間違ってる。スレッドがSTILL_ACTIVE返したら区別つかない。
 WaitForSingleObject(スレッドハンドル) == WAIT_OBJECT_0 で判断しろ
・ThreadProcで(const Thread&)のキャストは要らないでしょ
・マップ操作前後のロックタイミングはこれでいいと思う
・suspend/resumeのロックはこれでいいと思う
・joinでWaitForSingleObjectの戻り値確認して
・isAliveにロックは不要
・クラス設計が変。currentThreadの返したThreadは何だ?
 実際のrunと関係ないrunを持つThreadをnewして返すのは絶対変だ
・Runnableとt_threadの使い分けをもう少し整理して
・ヘッダ名見直せ。<cstdio><windows.h><process.h><map><cstdio><sstream>

> tb=thread_pool_for_runnable[target];//既にあるRunnableの時はそれを使う
? エラー返すべきでは?

あと、ミューテックスのロックはヘルパークラス作れ。
コンストラクタでミューテックスを受け取ってロックし、デストラクタでアンロック。
でないと途中で例外が発生したときにいちいち対処できない。

> もう全然うまくいかないので
何がうまくいかない? 何となく動きそうだが。
コンパイルエラーとか言ったら殺
778デフォルトの名無しさん:2008/06/10(火) 07:15:40
今携帯なんで、後で詳しく見ますが、うまくいかないというのは
これで画像読み込みをしたときに画像読み込みが出来なかったりするんです
実験中には終了時に不正アクセスみたいのが出たり…
779デフォルトの名無しさん:2008/06/10(火) 14:38:51
777が優しすぎる
俺が男なら惚れてたね
780デフォルトの名無しさん:2008/06/10(火) 14:56:56
俺は男だから惚れた
781デフォルトの名無しさん:2008/06/10(火) 16:38:37
じゃあ掘れるのか
782デフォルトの名無しさん:2008/06/10(火) 19:43:21
惚れたけど掘れない。
783719:2008/06/10(火) 20:22:05
いやぁ、勉強になるなぁ…。
784デフォルトの名無しさん:2008/06/11(水) 07:10:26
質問があります
pthreadでは途中でスレッドをキャンセルする場合
pthread_cancelを遅延キャンセルでコールして、
クリーンナップハンドラでリソースを開放するという方法が考えられますが、
C++では実行環境(gcc,glibc)によって、クリーンナップ内でオブジェクトの
デストラクタが呼ばれなかったり、例外処理が行われないなどといったことがあるみたいですが、

「C++ではこのようにしてpthreadを中段させるべき」といった
定石的手法が確立しているのでしょうか?

できればURIなど情報源などもあれば教えてください。

【OS】
Linux2.6
【言語】
C++
【実行環境】
RHEL5(pthread)
【その他突起する事項】
「RHEL5の中のライブラリならサポートしてるので気にするな」ってのは無しで
785デフォルトの名無しさん:2008/06/11(水) 07:47:54
外から中断なんかしない。
当たり前すぎて泣けてくる。
786デフォルトの名無しさん:2008/06/11(水) 12:24:11
>>784
安全に中断させる方法なんて存在しない。

だが、スレッドのエントリ関数のreturnを実行して正しく終了させる方法はいくらでもある。
787デフォルトの名無しさん:2008/06/11(水) 13:55:11
> 「C++ではこのようにしてpthreadを中段させるべき」といった
> 定石的手法が確立しているのでしょうか?
中断通知機構は自分で独自に実装。必ずエントリポイントの関数まで
戻るようにする。
異常時に終了するため、終了用の例外クラスを作成。エントリポイントのみ
でcatchし、他はクラスに対し例外中立なコードを書く。
ソースは俺。
788デフォルトの名無しさん:2008/06/11(水) 14:04:26
>>778
joinせずに終了したか、Thread,Runnableのメモリが誤って解放されたのでは
789デフォルトの名無しさん:2008/06/11(水) 20:40:04
スレッド止めてプロセスにする
790777:2008/06/11(水) 21:51:22
>>775
GetLastErrorの戻り値判定ロジックが逆。
細かい間違いは修正したが普通に動いた。元のろだ?のup方法がわからなかったので↓にup
http://www11.axfc.net/uploader/He/so/108823.zip
DLパスは mt

さすがにmy_ptrとかいうのはboost::shared_ptrに置き換えさせてもらった。
791デフォルトの名無しさん:2008/06/11(水) 22:28:58
アクターモデルって奴の
C++とかjavaとかでのサンプルない?
792デフォルトの名無しさん:2008/06/11(水) 22:36:55
761です
>>790
ブワッ!なんと言うやさしさ・・・やっと時間が取れたので、777を元に修正してたら、なんという
でも俺はウホじゃないです。すいません

(const Thread&)のキャストですが、こうしたらローカル変数の寿命がどうたらで1個分生成・破棄の
コストが浮くかなあと思って付けたんですが・・・まぁ、確認もせずにつけたので効果はいざ知れず

> currentThreadの返したThreadは何だ?
この関数を実行したスレッドがスレッドプール内に存在すれば、そのスレッドを操作する
Threadオブジェクトを返します。
既存のRunnableの時再利用するのは
Hoge(){
Thread th(this);th.start();
}
~Hoge(){
Thread(this).join();
}
とすることに憧れていたからです・・・。つまり俺がちょっとおかしいのです
793デフォルトの名無しさん:2008/06/11(水) 23:27:08
pthread mutexで

読みスレッドが2人
書きスレッドが2人

といる場合、rwlock使うと読んでる間に
書き込もうとしてもロックされる?


794デフォルトの名無しさん:2008/06/12(木) 00:24:12
pthreadは知らないけど一般のReader-Writer-Lockなら排他制御されなぎまずいんじゃね。
Readerのみの場合に排他されないんだと思う。
 Reader vs. Reader → 排他されない
 Reader vs. Writer → 排他される
 Writer vs. Writer → 排他される
795デフォルトの名無しさん:2008/06/12(木) 00:38:59
Pthreadもそうだったと思う
Man読みゃいいんだけどね
796デフォルトの名無しさん:2008/06/12(木) 01:47:42
スレッドAがrdlockする
スレッドBがwrlockしようとする(が、rdlock中なのでブロック)

この状態の時に、スレッドCがrdlockしようとすると
1.スレッドCがrdlockを取得(Aと共存)出来る
2.スレッドB(ロック獲得優先権がある)の処理終了までブロックする
一般的にはどうなる?

・一般的に、rwlockと呼ばれるものの動作として決まっている(どっち?)
・pthreadの標準として決まっている(どっち?)
・何も決まってない(実装依存)
797デフォルトの名無しさん:2008/06/12(木) 01:54:39
>>796
http://opengroup.org/onlinepubs/007908775/xsh/pthread_rwlock_rdlock.html
> It is unspecified whether the calling thread acquires the lock
> when a writer does not hold the lock and there are writers waiting for the lock.

何も決まってないぽい
798デフォルトの名無しさん:2008/06/12(木) 02:00:50
おー、thx
799デフォルトの名無しさん:2008/06/13(金) 22:28:31
761です。
http://ccfa.info/cgi-bin/up/src/up20298.zip
どうやらスレッドクラスの使い方が悪いのかもしれないので、そこだけ見ていただけないでしょうか?
main.cppです。お願いします<(_ _)>
800777:2008/06/13(金) 23:54:51
>>761
これ以上はスレが荒れるといかんのでやめてくれ。これが最後だ。
・サブスレッド実行したままmain終了するな
・vector<image>は大丈夫か? imageのコピーコンストラクタ呼ばれまくるぞ
・「LockでWaitForSingleObjectの戻り値確認しろ」って言ったよな? 聞いてる?
 同期オブジェクトをロックしたまま自身をサスペンドしたら誰がロック解除するんだ
 → 罰として、Win32APIの全呼び出しをエラーチェックしろ
 → 罰として、全行の間にデバッグ用のprintf入れて何が起きてるか理解しろ
 → 罰として、「これはmainスレッドから呼ぶ」/「これはサブスレッドから呼ぶ」
   のコメントを全関数に書け
 → 罰として、これから一年 SuspendThread の使用を禁ず。危険すぎる。
   お前のやりたいことをするにはpthreadの条件変数を使うのが自然だが
   Win32には無いのでとりあえずresume/suspendを ↓ に書き直せ
class x {
  HANDLE suspend_lock;
protected:
  void i_am_Thread_and_i_will_wait_until_someone_resume_me()
  { ::ResetEvent(this->suspend_lock);
    ::WaitForSingleObject(this->suspend_lock, INFINITE); }
public:
  x() : suspend_lock(::CreateEvent(NULL, TRUE, FALSE, NULL)) {}
  void run() { /* .......*/ }
  void i_am_main_and_i_resume_Thread()
  { ::SetEvent(this->suspend_lock); }
};
801デフォルトの名無しさん:2008/06/14(土) 00:12:59
なんて優しい罰だ!

802デフォルトの名無しさん:2008/06/14(土) 14:49:30
スレッドを作成して、そのスレッド内でエラー用のMessageBoxや
設定変更の為のプロシージャを起動させると
CPU使用率が100%になってしまいます。
これってどうやって回避すればいいのでしょうか?
803デフォルトの名無しさん:2008/06/14(土) 14:54:14
>>802
もっと詳しく
804デフォルトの名無しさん:2008/06/14(土) 15:11:12
簡単にすると、スレッドのメッセージループにおいて―――

while(0)
{
switch(message)
case WM_KEYDOWN:
MessageBox(NULL, "メッセージボックスの表示", "test", WM_OK);
break;
}

……という場合、メッセージボックスを表示させるとCPU使用率が100%になるんです。
メンバにコールバック関数を組み込んだクラスでダイアログボックスを表示させても同様です。
回避方法ってないもんでしょうか。
805デフォルトの名無しさん:2008/06/14(土) 15:17:28
スレッド生成して呼び出し元が先に終了しても、スレッドは動き続ける?
806デフォルトの名無しさん:2008/06/14(土) 16:37:21
WAIT_ABANDONEDってタイムアウトを設定してても
WAIT_OBJECT_0やWAIT_TIMEOUTが返らずにただ非シグナルになったことだけを返しちゃうの?
807デフォルトの名無しさん:2008/06/14(土) 16:58:22
ミューテックスを獲得できた結果、非シグナルになったのでは?
WAIT_OBJECT_0 と同じに扱えばいいと思うけど
808デフォルトの名無しさん:2008/06/14(土) 17:56:42
>>807ありがとう。日本語苦手なんだよね・・・。
809デフォルトの名無しさん:2008/06/14(土) 18:38:36
>>808
英語でおk
810デフォルトの名無しさん:2008/06/14(土) 19:54:40
>>804
そのコードから読み取れるものは何もないし、おそらくMessageBoxうんぬんは全く関係ない。
スレッドのメッセージループというのは、スレッドをUIスレッドにしてるのか?
それともPostThreadMessage用のGetMessageだけの簡易版なのか?
811デフォルトの名無しさん:2008/06/14(土) 22:25:19
>>810
>> while(0)

ネタでしょ。
812デフォルトの名無しさん:2008/06/15(日) 00:24:48
デバッガで追えばわかるでしょ。デバッガが無理でもログ出せば
何が起きてるかわかると思うが。
グローバルにFILE* f宣言してWinMainの最初でfopenしてfprintfでログ出す。
そのぐらいは確認してから訊いて欲しいなぁ。
813719:2008/06/15(日) 03:06:12
boost::thread使うことにしました。で、suspend、resume、cancelを実装したいのですが、
以下のような使い方で間違っていないでしょうか?
気になるのは※1の箇所のmutexが何のためのmutexかよくわからない点なんですが…。

case IDM_KEY_ESCAPE: { // エスケープキーを押したらサスペンド
runnable->suspend();
if (MessageBox(hwnd, TEXT("Quit the thread?"), TEXT("CANCEL"), MB_OKCANCEL|MB_ICONQUESTION|MB_DEFBUTTON1)==IDOK) { runnable->cancel(); } // OKでスレッド中止
else { runnable->resume(); } // CANCELでスレッド再開
break;
}

Runnable::Runnable(void) : cancel_(false), suspend_(false), is_running_(false) {}
void Runnable::suspend(void) { suspend_ = true; }
void Runnable::resume(void) { suspend_ = false; condition_.notify_one(); }
void Runnable::cancel(void) { cancel_ = true; condition_.notify_one(); }
void Runnable::operator()(void) {
is_running_ = true;
while (1) {
if (suspend_) { boost::mutex::scoped_lock lock(mutex_); condition_.wait(lock); } // ※1
if (cancel_) break;
...処理...
}
is_running_ = false;
suspend_ = false;
cancel_ = false;
}
814デフォルトの名無しさん:2008/06/15(日) 03:24:49
泥沼の予感
815デフォルトの名無しさん:2008/06/15(日) 15:35:56
>なんて優しい罰だ!
純愛系ソフトSM?
816デフォルトの名無しさん:2008/06/15(日) 15:38:21
まともに書けない(or書きたくない)香具師はOpenMPを使ってろよ。
下手な実装よりもよっぽど巧く動くし簡単だぞ。
817デフォルトの名無しさん:2008/06/15(日) 23:03:59
>>805
Windowsの場合、全スレッドが終了するまでプロセスが終了しない。
でもC Runtimeライブラリの後始末とか走るかもしれないので危険かも知れない。

Javaは知らん。

.NET Frameworkの場合、スレッド属性を「フォアグラウンド」/「バックグラウンド」
の切り替えが出来て、バックグラウンドにした場合はMainが終了するとサブスレッドも
終了。
818デフォルトの名無しさん:2008/06/15(日) 23:20:15
今回のコードでは不要だけど、制御の切り替わりの時に他の変数も一緒に変更して
あげなきゃいけないようなときに、notify_one側とwait側の両方で該当箇所の前後を含めて
排他制御するため、だと思う。
819デフォルトの名無しさん:2008/06/16(月) 13:36:24
>>817
javaはデーモンスレッドじゃないスレッドがいなくなったら終わる。
Thread.setDaemonで切り替える。
.NETのバックグラウンド相当かな。
820719:2008/06/16(月) 16:07:59
>>818
今回のコードに関しては意味的には不要ということであってるわけですね。
将来的に必要になってくる気がしますけど。
ありがとうございました〜。
821818:2008/06/16(月) 22:29:34
訂正。>>813はsuspend_の変更とロックをアトミックに行わないとだめな気がする。

void Runnable::suspend(void) { boost::mutex::scoped_lock lock(mutex_); suspend_ = true; }

void Runnable::resume(void) { boost::mutex::scoped_lock lock(mutex_); suspend_ = false; condition_.notify_one(); }

while (true) {
  {
    boost::mutex::scoped_lock lock(mutex_);
    if (suspend_) { condition_.wait(lock); }
  }
822デフォルトの名無しさん:2008/06/18(水) 20:56:22
>>802ですが、自己解決しました。
メインのメッセージプロシージャにおいて下記のようにしていたことが原因でした。

switch(message)
{
  case WM_KEYDOWN:
  
    (中略)

  default:
    PostThreadMessage(MainThreadID, message, wParam, lParam);
    return DefWindowProc(hWnd, message, wParam, lParam);
}

このため、スレッド内で別のメッセージループを持つ関数を起動させると
CPU使用率が100%になっていました。
お騒がせしました。
823719:2008/06/18(水) 21:32:49
>>821
親切にどうも。その後>>813ではうまくいかないタイミングがあり、
>>821にあるようにsuspend、resumeにlockを追加したのですが、
whileの部分を

  if (suspend_) {
    boost::mutex::scoped_lock lock(mutex_);
    condition_.wait(lock);
  }

としていました。これだとうまくいかず考えてたんですが
>>821で解決できそうです。
824デフォルトの名無しさん:2008/06/19(木) 00:49:45
>>822
すまないがゆとりの俺には理解できなかった。もう少し説明プリーズ。

メインスレッドのメッセージループでサブスレッドにメッセージをPostする
ことと、サブスレッドでメッセージボックスを出すことで、どうしてCPUが100%なの?

せいぜいメッセージボックスが何度か再帰呼び出しされるだけに見えるが。
825デフォルトの名無しさん:2008/06/20(金) 15:22:25
>>800のvoid i_am_Thread_and_i_will_wait_until_someone_resume_me()って
この関数を呼んだスレッドが停止しちゃうんだよね?やっぱり変なタイミングで
スレッドを停止しないようにってこと?
826デフォルトの名無しさん:2008/06/20(金) 19:26:46
タイミングの問題じゃないよ。単に実装が間違ってた。
元々のコードに書いてあったのは「サブスレッドが自分の処理を終えると待ちに入る」こと。
ところが、メインスレッドがサブを再開させようとするとデッドロックするバグがあったので
そうならないように書き直した。

「誰かが起こしてくれるまで眠り続ける薬」を、部屋の内側から鍵かけて飲むような
作りになってた。
827デフォルトの名無しさん:2008/06/20(金) 19:44:44
>>826あ、気になってたんですがstaticオブジェクトのデストラクタってどのスレッドが実行してるんでしょうか?
828デフォルトの名無しさん:2008/06/20(金) 20:52:08
C++の言語仕様はスレッドの概念が無いので規定がない。
気になったらまず確認しろ。仕様は不明でも特定の処理系の実装はわかる。

#include <windows.h>
#include <cstdio>
struct x {~x() {std::printf("%d\n", ::GetCurrentThreadId());}} obj1;
int main() {x();}
829デフォルトの名無しさん:2008/06/20(金) 20:58:28
スレッド関数内で作った static オブジェクトのことじゃないのか?
830デフォルトの名無しさん:2008/06/21(土) 00:06:00
exit() を実行したスレッドじゃないか? と当てずっぽうに言ってみるが
831デフォルトの名無しさん:2008/06/21(土) 03:44:02
>>830
Microsoftはそーみたいだね。その関数の存在忘れてたわ。

>>829
exitのケースを除いて、スレッド関数内のstatic変数をそのスレッドで
破棄したら言語仕様を満たせなくなるんでない?
破棄のタイミングはmain関数より後なんで。
832デフォルトの名無しさん:2008/06/21(土) 16:42:58
そもそも「スレッド関数内で作った static オブジェクト」ってなんだ?
833デフォルトの名無しさん:2008/06/21(土) 16:48:52
スレッドに渡すコールバック関数内にstaticなオブジェクトがあるという話しだろ
834デフォルトの名無しさん:2008/06/21(土) 17:30:27
それを「関数内で作った」って言うのか?

もし本気でそう思ってるなら、もうし少し static オブジェクトについて
勉強したほうがいいんじゃないか。
835デフォルトの名無しさん:2008/06/21(土) 17:57:44
文法上のレベルとコンパイル後のレベルを比べられてもなぁ…
836デフォルトの名無しさん:2008/06/21(土) 18:06:58
俺には834の方が何を意図しているのかよく分からん。
837デフォルトの名無しさん:2008/06/21(土) 18:13:09
なんとなく
void hoge(){
  static int x;
}
みたいな関数があるとき、関数内に書いた≠関数内で作った、って言いたいんじゃないかと想像
838デフォルトの名無しさん:2008/06/21(土) 18:26:26
いろんなスレッドがhogeを呼び出してなんどもコンストラクタが呼ばれるんですね
わかります
839デフォルトの名無しさん:2008/06/21(土) 18:59:43

dataが今456000000000個あります。

これを312台のマシンで分割して計算したいのですが
何を勉強すればいいのでしょうか?
840デフォルトの名無しさん:2008/06/21(土) 19:00:14
MapReduce
841デフォルトの名無しさん:2008/06/21(土) 19:15:45
マジレスするとRuby
842デフォルトの名無しさん:2008/06/21(土) 19:24:29
>>839
OpenMP
843デフォルトの名無しさん:2008/06/21(土) 19:26:07
スレッドというか分散処理
844デフォルトの名無しさん:2008/06/21(土) 19:33:07
Erlang
845デフォルトの名無しさん:2008/06/21(土) 19:42:14
>>839
スレ違いであるということを勉強したらいいと思うよ。
846デフォルトの名無しさん:2008/06/21(土) 22:44:47
>>836-837
>>837 の例だと、x は、hoge() に入る前から存在するんだから
「関数内で作った」と言われるとすごい違和感があるんだが、
俺の感覚の方がおかしいのかなぁ。

>>838
「関数内で作った」とか言われたら普通そう思うよな。
847デフォルトの名無しさん:2008/06/21(土) 23:01:14
関数内のstatic変数が初期化されるのは、初めて実行されるときじゃなかったか?
そういう意味なら「関数内で作った」と言ってもそれほど変だとは思わないな。
848デフォルトの名無しさん:2008/06/21(土) 23:16:33
>>846
> hoge() に入る前から存在するんだから
しないよ。それは規格(ISO/IEC 9899:1999, ISO/IEC 14882:2003)で決まってる。
void thread_entry()
{
  static struct x = some_func();
}
xは最初に制御がここを通るときに生成される。
849デフォルトの名無しさん:2008/06/21(土) 23:23:18
あ、「生成」っていうのは実装としてメモリが確保されるとかじゃなくて、
概念的にオブジェクトが利用可能な状態になるってことね。
850デフォルトの名無しさん:2008/06/21(土) 23:40:18
void in_thread_func() {
 static std::string("あいうえお");
}
も同じだね。

大体、「デストラクタ」と言っているのだから
POD型ではないので、「(大抵の処理系で)実行開始時に確保されてる」等の
Cの話は関係ない。
むしろ、こういうものだと捉えない>>832>>846が不思議。

あ、デストラクタの呼び出し順は、生成と逆順であることが保証されているよ。
実装的には、初期化時はフラグ(大抵排他制御されてない)を使って判定して
内部的にatexitのようなもの登録することで
デストラクタを呼び出しているものが多いみたいね。
851デフォルトの名無しさん:2008/06/22(日) 00:03:36
>>850
> デストラクタの呼び出し順は、生成と逆順であることが保証されているよ

関数内のstaticオブジェクトも?
MAJIDE?
852>>836:2008/06/22(日) 00:13:02
>>847-850
すまん、確かにお前等の言うとおりだった...。

全然勘違いしてた。orz

>>831
> 破棄のタイミングはmain関数より後なんで。

そもそも、main 関数終了後まで生き続けるスレッドなんて言うものを
言語仕様策定時に想定していなかったか、想定しててもそれはプログ
ラマ側の責任だよと言うことなんだろうな。
853>>836:2008/06/22(日) 00:21:38
>>851
> 関数内のstaticオブジェクトも?
> MAJIDE?

マジみたい、

VC++ 2005 でやってみると、コンストラクタを実行する時にデストラクタを
登録している。

>>850 の言う通り初回かどうかの判定は排他制御されてないフラグでやって
るからマルチスレッドだと注意しないとえらいことになりそう。
854デフォルトの名無しさん:2008/06/22(日) 01:24:12
ここ30年前ほど悩んでいるのだけれど、静的変数の初期化ってどうやって排他する
のでしょうか?

void f() {
static class X i; // ←初期化が排他制御されない。
}

これを回避するために

void f() {
X* px;
static Mutex mutex;
{
MutexLock lock(mutex);
static class X i;
px = &i;
}
px->zzz();
}

としたのですが、mutexの初期化が排他制御できないのです。
mutexをメインスレッドに置くぐらいしか思いつきませぬ。
855デフォルトの名無しさん:2008/06/22(日) 01:36:52
mutexを関数の外に出せば、main実行前にメインスレッドで初期化されるね
856デフォルトの名無しさん:2008/06/22(日) 02:17:49
C互換構造体を使う(BinaryHacksより)
って方法はダメ?
857デフォルトの名無しさん:2008/06/22(日) 02:19:08
>>855
static initialization order fiascoが問題になる
858デフォルトの名無しさん:2008/06/22(日) 02:21:16
一般的には、lockを関数の外に出して、コンストラクタで初期化するべき。

何か事情があって、どうしても関数内で行う必要があるとき(例えばDLL内など)は
CASを使ってlockへのポインタを初期化することで、なんとかなる。
オブジェクトが複数確保しても(余剰分はすぐ解放する)コスト等で問題ないなら
オブジェクト自体をCASを使って確保する手もある。
859デフォルトの名無しさん:2008/06/22(日) 06:26:44
マルチスレッドには関係ないがVBのStaticには何度もだまされた記憶がある
860デフォルトの名無しさん:2008/06/22(日) 11:24:20
>>858
CASってあんまり知らないけど、マシン語レベルでメモリに書き出したつもりでも
片方のスレッドだけCPUキャッシュでライトバックされて矛盾とか起きないの?
ちなみにWindowsだったら名前付きイベントで同期が可能かなと思った。
861デフォルトの名無しさん:2008/06/22(日) 11:30:48
>>854
threadが一つのうちに済ませればおk

>>855
そいつは処理系依存
862デフォルトの名無しさん:2008/06/22(日) 11:52:53
>>860
矛盾が起きないようにするためのキャッシュアルゴリズムなのである。
863>>836:2008/06/22(日) 12:43:13
>>854
> ここ30年前ほど悩んでいるのだけれど、

C++ が開発されてまだ 25年しか経ってないんだけど、未来からお越しの方ですか? (w

>>861
> >>855
> そいつは処理系依存

「mutexを関数の外に出せば、main実行前にメインスレッドで初期化されるね」とならない
処理系なんてどうやって作るんだ?

# >>854 が「mutexをメインスレッドに置くぐらいしか思いつきませぬ。」って書いてるか
# ら、>>855 の書き込みはあまり意味がないというなら分かるが。
864デフォルトの名無しさん:2008/06/22(日) 12:44:07
rw_lockの実装ってどっかにのってないですか?
865デフォルトの名無しさん:2008/06/22(日) 13:03:05
866デフォルトの名無しさん:2008/06/22(日) 13:34:59
>>865
JAVA解らんCかC++でw
867デフォルトの名無しさん:2008/06/22(日) 14:15:03
後出しジャンケンって嫌われるよね
868デフォルトの名無しさん:2008/06/22(日) 15:40:10
>>860
例えばWindowsなら、InterlockedCompareExchange()を調べてみ
869デフォルトの名無しさん:2008/06/22(日) 21:46:05
Java Docを見たのですが、ThreadLocalが何のために使うのかわかりません。
どこかわかりやすく説明しているサイトはないでしょうか?
870デフォルトの名無しさん:2008/06/22(日) 21:59:09
用途のわからないものをわざわざ使おうとする必要はないような・・・
871デフォルトの名無しさん:2008/06/22(日) 22:39:58
まあそんなことを言うと進歩がないわけで、興味を持つのは
悪くないと思うよ。

ただ、ThreadLocal は Thead でいろいろやらないと必要性が
ちょっと分かりにくいものだから、Thread で色々遊んでから
調べた方がいいかも知れない。

機能としては、Java Doc に書いてある通りだし。
872デフォルトの名無しさん:2008/06/22(日) 22:50:44
>>869
セキュリティとかトランザクションとかスレッドに結びつけた情報を覚えておくため
873デフォルトの名無しさん:2008/06/23(月) 02:56:56
>>869じゃないけど俺もTLSの使い道がわからない。
特にJavaみたいなガベージコレクションのある言語なら
Runnableクラスに変数1個定義するだけで十分に思えてしまう。
874デフォルトの名無しさん:2008/06/23(月) 03:44:08
例えば
http://www.google.com/codesearch?q=__thread
とか。
あ、__threadってのは、Win32における一般的なTLSのキーワードな。

で、ぱっと見ただけでも、errnoとかに使われてる。
まあそれ以外はコードをよく見てないからわかんないけど。
875デフォルトの名無しさん:2008/06/23(月) 03:47:59
あれ、errnoは普通は関数呼び出しに置き換わるんだっけ?
まあ、それでも内部的にはその呼び出し内で使われてるでしょ。普通は。
876デフォルトの名無しさん:2008/06/23(月) 03:54:45
ていうか__threadって、Win32に限らんな。
sunやhpのマニュアルもヒットするし
gccも3.3以降なら__threadで使えるのか。
877デフォルトの名無しさん:2008/06/23(月) 07:26:35
Javaで別のスレッドで作られたオブジェクトに対してメソッド呼び出しすると、
どっちのスレッドで動くの?
混ざり合わないの?

class Hoge implements Thread{
  private Object o; // Hogeスレッドのもの?
  public static void main(String[] args){
    new Thread(new Hoge()).start();
    new Thread(new Piyo()).start();
  }
  public Hoge(){ Thread.currentThread().setDaemon(true); }
  public void run(){ setValue("aa"); }
  public void setValue(Object v){ o = v; } // Piyoスレッドから呼ばれたときはスレッド固有の値同士が混ざり合わないの?TLSじゃないの?
}

class Piyo implements Thread{
  public Piyo(){ Thread.currentThread().setDaemon(true); }
  public void run(){ setValue("bb"); }
}
878デフォルトの名無しさん:2008/06/23(月) 08:34:38
根本的にわかってないでしょ。
もうちょっと書籍とか呼んでがんばって濃い。
879デフォルトの名無しさん:2008/06/23(月) 08:42:21
まぁヒープ領域に確保されたオブジェクトはスレッドと関連付けられてるのかって聞きたかっただけなんだけどな
880デフォルトの名無しさん:2008/06/23(月) 09:19:48
javaもアノテーションでTLSできたら楽なのにね。
@threadlocal static int hoge = 0; みたいな感じで。
881デフォルトの名無しさん:2008/06/23(月) 10:42:51
>>879
どうみてもそういう話じゃないな
882デフォルトの名無しさん:2008/06/23(月) 11:04:52
え?じゃあどういう話だったの?
883デフォルトの名無しさん:2008/06/23(月) 11:50:27
javaのThreadLocalは、staticなメソッドで必要なオブジェクトを毎回作りたくないときに使う。
もちろんそのオブジェクトがスレッドセーフならかまわないけど。
884デフォルトの名無しさん:2008/06/23(月) 20:29:29
>>882
スレッドとかいう話じゃなくて、インスタンス変数の概念が無かった
という話。だから
> private Object o; // Hogeスレッドのもの?
こういう疑問が生まれる。

> public Hoge(){ Thread.currentThread().setDaemon(true); }
これはひどい・・・
885デフォルトの名無しさん:2008/06/23(月) 20:36:57
ThreadLocalと言うと
>Runnableクラスに変数1個定義
出来ない場合にも使うよな。
フレームワークでThreadを管理している場合とか。
886デフォルトの名無しさん:2008/06/23(月) 21:00:15
>>884
いやインスタンス変数というか,インスタンスとかクラスベースオブジェクト指向言語の話題は十二分に分かってると自負してるんだが
JavaのスレッドがWinAPIのスレッドと結構毛色が違うので混乱していた

まだちょっと分からないんだけど,Javaのオブジェクトってスレッドに関連付けられて作られるわけじゃないの?
ただのヒープ領域に割り当てられるだけなの?


> > public Hoge(){ Thread.currentThread().setDaemon(true); } 
> これはひどい・・・
run()に書くべきだった・・・
887デフォルトの名無しさん:2008/06/23(月) 21:43:46
ヒープが自動的にスレッドローカルになるの>WinAPI
888デフォルトの名無しさん:2008/06/23(月) 21:46:21
Javaのスレッドはどうなってるのか聞いてみた
889デフォルトの名無しさん:2008/06/23(月) 21:51:35
>Javaのオブジェクトってスレッドに関連付けられて作られるわけじゃないの?
>ただのヒープ領域に割り当てられるだけなの?
Yes。スレッドとは縁もゆかりもない。スレッド固有でもなければスレッドごとに
値が異なるわけでもない。ただnewした数だけインスタンスが存在する。

>>887
イミフメ
890デフォルトの名無しさん:2008/06/23(月) 21:53:22
ドトネトのForms連中が、ThreadAffinityのある全メソッド・プロパティで
保存しておいた作成時ThreadIDと、実行中のThreadIDを
チェックして例外発生させてたけど、そんな感じが自動実装されるってか?
891デフォルトの名無しさん:2008/06/23(月) 22:05:44
>>889
はあく
これで安心してJavaプログラミングできるわ
892デフォルトの名無しさん:2008/06/23(月) 22:05:50
初カキコです。
C++です。beginthreadexで作ったスレッドを処理途中で強制的にリセット
(処理開始前の状態)できるきるような便利な機能ってありますか?
なければどなたか実装方法アドバイス頂けないでしょうか?
アセンブラとかいじればできるのかな〜?
893デフォルトの名無しさん:2008/06/23(月) 22:24:58
パンプティダンプティ割れてしまった卵は・・・
Transactinal Memoryで何とかなるのだろうか
894デフォルトの名無しさん:2008/06/23(月) 22:33:05
スレッド関係ねぇな
895デフォルトの名無しさん:2008/06/24(火) 16:19:50
>>892
イベントなりフラグなり立てて処理をキャンセル汁
896デフォルトの名無しさん:2008/06/24(火) 16:28:08
      r ‐、
      | ○ |         r‐‐、
     _,;ト - イ、      ∧l☆│∧   良い子の諸君!
    (⌒`    ⌒ヽ   /,、,,ト.-イ/,、 l   
    |ヽ  ~~⌒γ⌒) r'⌒ `!´ `⌒)  人生にリセットボタンは無いが
   │ ヽー―'^ー-' ( ⌒γ⌒~~ /|   電源ボタンはあるんだ!
   │  〉    |│  |`ー^ー― r' |    
   │ /───| |  |/ |  l  ト、 |  めんどくさくなったら押してみるのも一興だな。
   |  irー-、 ー ,} |    /     i
   | /   `X´ ヽ    /   入  |
897デフォルトの名無しさん:2008/06/25(水) 01:04:03
>>892
できないし、実装しようとするのも勧められない



共有変数 A = 0として
スレッド1がAをインクリメント
スレッド2がAをインクリメント
スレッド1リセット
Aの値は?
898デフォルトの名無しさん:2008/06/25(水) 07:52:41
>>897
あおりはスルーでおねがいします

>アセンブラとかいじればできるのかな〜?
899デフォルトの名無しさん:2008/06/25(水) 08:13:17
アセンブラに夢持ちすぎ
とりあえず素直にユーザが実装すべき
900デフォルトの名無しさん:2008/06/25(水) 12:42:29
普通に実装すりゃ簡単に実現できるが、めんどくせぇとかほざいてんのか?
「スレッドを初期状態に戻す」とか
「リセットしたくなったら」とか
定義が曖昧でよくわからんが
スタック変数にリソース管理させてリセットしたくなったら例外でも投げとけ。
そんなコードを仕事で見かけたら糞味噌にするが趣味コードなら誰も文句いわねーよ
901デフォルトの名無しさん:2008/06/25(水) 12:43:42
なんとここで釣れた釣れた宣言が・・・!!
902デフォルトの名無しさん:2008/06/25(水) 12:51:00
あるスレッドでHDDを初期化しまんた
スレッドをリセットしたので初期化したHDDが元に戻りまんた

こんなのにも万能に対応しろってことかい?
903デフォルトの名無しさん:2008/06/25(水) 12:55:32
なんという参照透過性による副作用の排除
904デフォルトの名無しさん:2008/06/25(水) 13:05:19
タイムマシン型スレッドを作って、スレッド消したら時間が戻る…
905デフォルトの名無しさん:2008/06/25(水) 13:55:02
データベースのロールバックみたいなもんかな
906デフォルトの名無しさん:2008/06/25(水) 13:56:19
PCIバスに差すやつで、リセットなり電源オフなりすると
HDDの内容元に戻るのがあったな。
907デフォルトの名無しさん:2008/06/25(水) 14:14:33
ループしてしまう
908デフォルトの名無しさん:2008/06/25(水) 20:08:59
なにそのデジタル版三途の川
909デフォルトの名無しさん:2008/06/25(水) 20:10:30
>>848
> しないよ。それは規格(ISO/IEC 9899:1999, ISO/IEC 14882:2003)で決まってる。

どうしてそんな嘘つくかなぁ…
ISO/IEC 9899:1999は隅々まで読んだが、そんなこと書いてないぞ。
910デフォルトの名無しさん:2008/06/25(水) 20:24:19
規格中はこれだから(ry
911デフォルトの名無しさん:2008/06/25(水) 21:14:42
C++の規格の関係ありそうなところだけ読んでみたが、>>837はPOD型だから
関数に入る前から初期化することが許されているな。
>>848の場合は「その宣言に初めて制御が渡った時点で行われる」と書いてある。
912デフォルトの名無しさん:2008/06/25(水) 21:32:23
でもCだと確かローカルなstaticは定数でしか初期化ができなくてそれもmainの実行前だよな。
913デフォルトの名無しさん:2008/06/25(水) 21:56:30
C99の6.2.4と6.7.8確認したが、定数式による初期化のみで、プログラム
実行前に初期化だな。
確かに「関数内で作った」と言われるとすごい違和感ある。

914デフォルトの名無しさん:2008/06/27(金) 07:19:15
読み込み専用ロックしてる最中に
別スレッドで書き込みが発生すると、データが強制的に書き換わるのですが
どうやって防止すればいいのですか?
915デフォルトの名無しさん:2008/06/27(金) 08:27:19
加齢にスルー
916デフォルトの名無しさん:2008/06/27(金) 08:51:25
>>914
読み込んだ値をTLSにコピー
917デフォルトの名無しさん:2008/06/27(金) 09:34:19
>>914
それは俺の国の言葉では「ロックできてない」と言う。
918デフォルトの名無しさん:2008/06/27(金) 12:24:31
>>914
書き込みロックを取得せずに書き込む奴が悪い
919デフォルトの名無しさん:2008/06/27(金) 12:56:38
先に読んでおいてスタックにでも置いとけ。
920デフォルトの名無しさん:2008/06/27(金) 13:06:38
>どうやって防止すればいいのですか?
バグを治す
921デフォルトの名無しさん:2008/06/27(金) 14:11:06
>>914
他スレッドに書込み許可を与えない
922デフォルトの名無しさん:2008/06/27(金) 18:08:17
mutexでロックしてるのに書き換わるよなんで?
923デフォルトの名無しさん:2008/06/27(金) 18:12:01
mutexをロックしただけなら、そのmutexを見ないやつには関係ないべ。
924デフォルトの名無しさん:2008/06/27(金) 20:30:11
>>914
ソースも貼らずに質問とな?
925デフォルトの名無しさん:2008/06/27(金) 22:08:59
mutexは他のデータをロックをしない。mutexデータだけがロックされる。
mutexと他のデーターの関連は自分でプログラムする。
926デフォルトの名無しさん:2008/06/27(金) 22:09:46
ロックしたのにロックされてねえ、
こりゃロックだ
927デフォルトの名無しさん:2008/06/27(金) 23:21:15
そんな症状が断言できるほど長時間のロックをする設計は間違っている。
928デフォルトの名無しさん:2008/06/30(月) 04:33:10
_beginthreadex()関数の第6引数が引っかかってなぜかコンパイルが通りません。
「'unsigned long' から 'void *' に変換することはできません。」と出ます。

DWORD ThreadID;
_beginthreadex(NULL, 0, (unsigned int (__stdcall *)(void *))MainThreadProc, NULL, CREATE_SUSPENDED, (unsigned int *)&ThreadID);

……と書いてるのですが、何が問題なのでしょうか?
環境はWindows2000, Visual C++ 6.0 SP5
process.hインクルード, [コード生成]→使用するランタイムライブラリ→マルチスレッドに指定しています。
929デフォルトの名無しさん:2008/06/30(月) 04:38:29
ちなみに、(unsigned int *)&ThreadID ……の部分をNULLにしても同様のエラーが出ます。
930デフォルトの名無しさん:2008/06/30(月) 05:31:47
まず、MainThreadProcがキャスト無しで渡せなければ話にならないのだけれど、
例えば__stdcallで良いのか、とか。
931デフォルトの名無しさん:2008/06/30(月) 05:32:59
VC9でそのコード丸ごとコピペしたら通ったけどな…。
ほんとにエラーそれだけ?
932デフォルトの名無しさん:2008/06/30(月) 06:38:40
>>930
3番目の引数をキャストなしで書くと以下のエラーがでます。
『3 番目の引数を 'unsigned long (void *)' から 'unsigned int (__stdcall *)(void *)' に変換できません。』

>>931
>>928のコードではエラーはこれ一つだけです。
933デフォルトの名無しさん:2008/06/30(月) 06:44:57
>>932
そこはキャストを使うべきではない。関数の宣言が違ってないか?
934デフォルトの名無しさん:2008/06/30(月) 06:59:12
よく見たらスレッド関数が
DWORD WINAPI MainThreadProc(LPVOID Param){〜略〜};
……になってました。
unsigned __stdcall MainThreadProc(void * Param){〜略〜};
に変更すると第3引数はキャストなしでもいけました。
しかし、第6引数を起因とするエラーは変わらずでます。

ちょっと落ちます。
935デフォルトの名無しさん:2008/06/30(月) 07:13:28
とりあえず、別にテスト用のプロジェクト作って
最小限のコードで問題が再現されるか試してみたらどうかな。
936デフォルトの名無しさん:2008/06/30(月) 21:12:21
つーか、MSのサンプルは通るのかい?
http://msdn.microsoft.com/ja-jp/library/kdzttdcb(VS.80).aspx
937デフォルトの名無しさん:2008/06/30(月) 23:29:53
pthreadで各スレッドローカル変数ってアクセス遅い?
938デフォルトの名無しさん:2008/07/01(火) 00:05:10
pthreadをなんだと思っているのだろう……
939デフォルトの名無しさん:2008/07/01(火) 00:11:26
スレッド作るやつ?
940デフォルトの名無しさん:2008/07/01(火) 04:52:09
名前の通りスレッドのポインタ
941デフォルトの名無しさん:2008/07/01(火) 05:39:47
>>928ですが、解決しました。
結果からいいますと、_beginthreadex()の返り値を"(HANDLE)"でキャストすることでコンパイルがとおりました。

HANDLE hThread=NULL;
DWORD ThreadID;
hThread=(HANDLE)_beginthreadex(NULL, 0, MainThreadProc, NULL, CREATE_SUSPENDED, (unsigned int *)&ThreadID);

なんともお騒がせしました。
ちなみにスレッド識別子ですが、宣言としてはCreateThreadの場合のように
DWORD ThreadID……でいいのでしょうか?
それともmsdnのサンプルのように、
unsigned ThreadID……の方がいいのでしょうか?
前者のように明示的に宣言する方が分かりやすくていいのですが、
後者だと第6引数をキャストする必要がなく簡潔に書けるので―――どうなんでしょう。
942デフォルトの名無しさん:2008/07/01(火) 06:25:58
CreateThreadが返すスレッド識別子と同じ物だろうし
どっちの型も(たぶん)32ビットだから、
キャストによる値の変化はないだろうという前提で……
一般的にはキャストしない記述が望ましいが、
理解して意図的にキャストするなら別に文句は言わない。
あとでThreadIDを使うときにみっともないキャストを連発するぐらいなら
最初からDWORD ThreadID;で定義したほうがマシかもね。
943デフォルトの名無しさん:2008/07/01(火) 07:18:23
>>DWORD ThreadID……でいいのでしょうか?
お前の使用している開発環境のヘルプにunsignedと書いてあるんだろ?
DWORDと書く理由が思いつかないのだが。仕様をみてプログラム書け。
944デフォルトの名無しさん:2008/07/01(火) 08:14:59
>>941
サンプルだけじゃなくWin32APIリファレンスやヘッダをよく読むのだ。
945デフォルトの名無しさん:2008/07/01(火) 08:33:15
longとintは“区別”しとけよボクぅ?
946デフォルトの名無しさん:2008/07/01(火) 08:59:03
>一般的にはキャストしない記述が望ましいが、
これはこの通りなんだが、戻り値はキャスト必須な時点でどうでもいいわなw
実質CreateThreadなんでCreateThreadと同じ変数を用意しておくのが無難ってもんだ。
てかこの程度でつまづくようなら大人しくboost他のラッパークラス使っておいた方がマシな気がしないでもない。
947デフォルトの名無しさん:2008/07/01(火) 09:00:11
longとintってなにが違うの?
両方とも32ビットの整数でしょ?
64ビット環境でもあるまいし。
948デフォルトの名無しさん:2008/07/01(火) 09:37:25
ここにも危険思想の持ち主がひとり…
949デフォルトの名無しさん:2008/07/01(火) 09:50:18
>>947 Unix界隈だと long 64bbit, int 32bit だったりするんだな
950デフォルトの名無しさん:2008/07/01(火) 09:51:42
64ビット環境でも LLP64 ならlongは32bitだけど・・・
951デフォルトの名無しさん:2008/07/01(火) 09:57:19
環境によってはintは16bitだな
952デフォルトの名無しさん:2008/07/01(火) 11:03:56
longって略さずにlong intって書こうぜ?
953デフォルトの名無しさん:2008/07/01(火) 21:14:51
だったらsignedもつけようぜ
954デフォルトの名無しさん:2008/07/01(火) 21:37:24
もちろんdouble floatもだよな?
955デフォルトの名無しさん:2008/07/01(火) 22:17:15
>>949
んな環境みたことねーぞ。例をあげてくれ。

>>954
イミフ
956デフォルトの名無しさん:2008/07/01(火) 23:14:48
>>955
Unix界隈
957デフォルトの名無しさん:2008/07/02(水) 00:04:43
>>955
SPARC/SolarisとかLP64(longとポインタが64bit)って呼ばれる環境がある。
旧DECのAlpha/Digital UNIXのようにILP64(int、long、ポインタが64bit)もある。
Win64のポインタが64bitでint、longが32bitってのは変態すぐる。
958デフォルトの名無しさん:2008/07/02(水) 00:10:34
>>955
Linuxだと long のサイズとポインタのサイズが同じという前提でプログラムが
書かれてることが結構ある(カーネルの時点ですでにそうだし)
64bit環境で普通にコンパイルすれば long が64ビットになる
959デフォルトの名無しさん:2008/07/02(水) 00:43:43
x64は64bitレジスタをいじる命令が32bitレジスタをいじる命令より1バイト長い
という食わせ物だから。intまで64bitにしたくないのはわかる。
960デフォルトの名無しさん:2008/07/02(水) 01:41:41
Win16のときのlong=32bitのまま引きずってるから、longを64bitに
できなかったんだろうな。
Win32ではintでいいところでlongを多用してるし。

まぁ、16bit時代から互換性を重視しながら続いているのが原因で、
しょうがないとは思う。生まれたときから32bitのOSとは事情が違うでしょ。

どうせtypedefされた型名しか使わないから、どこかの時点でlongを
使っている部分をintに変えてもよかった気はするけどね。
961デフォルトの名無しさん:2008/07/02(水) 01:50:54
long long
どっかの南の島の爺さんが語る昔話の話し出しみたいな
ろぉんぐ、ろぉんぐ、あるところに・・
962デフォルトの名無しさん:2008/07/02(水) 02:07:32
API自体が使うのはLONGとかDWORDとかINT_PTRとかなんだから、
別にCのlongが64bitだろうが行けなくはないはずなんだがなー
963デフォルトの名無しさん:2008/07/02(水) 05:03:19
Linux(笑)
964955:2008/07/02(水) 07:26:01
>>956
32ビット環境でlongが64ビットの例が欲しかったのだが・・・。JavaとかC#みたいな。
>>957
Alphaは大昔に使ったけどintは32では?
965デフォルトの名無しさん:2008/07/02(水) 09:56:17
初心者ですが、32bit Windows環境だと
単なる "unsigned宣言" は "unsigned long宣言" と同義ということですか?
966デフォルトの名無しさん:2008/07/02(水) 10:06:25
言語的には unsigned は unsigned int と同義。

で long がたまたま int と同じ長さだと、そうなる。
967デフォルトの名無しさん:2008/07/02(水) 13:06:30
SGIのにILP64なのがあったはず。AlphaはLP64でしょ。
968デフォルトの名無しさん:2008/07/02(水) 14:00:58
>>962
API自体のインターフェースが変わっている罠。
DWORDを受けていたのにULONG_PTRに変わったこれとか。
http://msdn.microsoft.com/ja-jp/library/cc429342.aspx
969デフォルトの名無しさん:2008/07/02(水) 20:49:14
同義じゃないだろ。
unsigned i1;
unsigned long i2;
std::printf("%s\n", typeid(i1).name());
std::printf("%s\n", typeid(i2).name());
i1とi2は「サイズが同じ」だけで同義じゃない。

あと『単なる "unsigned宣言"』という前提から少し外れるが、ポインタの互換性はない。
typedef unsigned long t1;
typedef unsigned t2;
t2 *p = (t1 *)0; // compile error
970デフォルトの名無しさん:2008/07/02(水) 22:39:04
同じ働きをすると言ってるだけで、誰も同じ型だとは言ってないよ。
971デフォルトの名無しさん:2008/07/02(水) 23:27:20
整数の型を省略したらsigned, intが勝手に着くとかあったなぁ
972デフォルトの名無しさん:2008/07/02(水) 23:28:02
main(c, char **s){
}
973デフォルトの名無しさん:2008/07/02(水) 23:35:36
最近は省略してもintと解釈しなくなったんじゃなかったっけ
974969:2008/07/03(木) 07:28:22
>>970
その「同じ働き」ってのが曖昧じゃないか。typeid比較する
コードがあったら違う挙動になるのは同じ働きとはいえないだろ。
サイズが同じだけで別の型だって念を押しておかないと>>965
unsignedとunsigned longの入り交じったソース量産するぞ。
975デフォルトの名無しさん:2008/07/03(木) 07:46:53
976デフォルトの名無しさん:2008/07/04(金) 07:35:27
posixのスレッドローカルデータって
上限値って決まってるのでしょうか
977デフォルトの名無しさん:2008/07/04(金) 08:44:28
データの個数?総サイズ?
978デフォルトの名無しさん:2008/07/04(金) 11:28:41
サイズなら上限は当然あるだろ
数値は実装に依存するが
979デフォルトの名無しさん:2008/07/04(金) 23:44:41
>>974
int a;
int b;

a と b のアドレスを比較するコードがあったら違う挙動になるんですが、
a と b は違う働きをするんですか?
980デフォルトの名無しさん:2008/07/04(金) 23:46:48
>>977
スタックサイズが64kbか128kbなので
個別スレッドで4Mのデータを扱えません
981デフォルトの名無しさん:2008/07/05(土) 01:02:35
>>980
なんで全てのデータをスタックに入れようとするんだよ。
982デフォルトの名無しさん:2008/07/05(土) 01:04:57
>>981
入れたいの
983デフォルトの名無しさん:2008/07/05(土) 06:46:06
>>979
違うとえば違うような。変数と型を一緒にしてない?
984デフォルトの名無しさん:2008/07/05(土) 07:06:39
>>980
回避方法はあるけど、TLSを使わない方針で設計を見直すべき。
985デフォルトの名無しさん:2008/07/05(土) 07:14:18
>>984
じゃあ使わないからどうやればいいのか教えてください
986デフォルトの名無しさん:2008/07/05(土) 09:13:34
スレッドごとにメモリを動的確保すればよい。メモリの解放には注意して。
987デフォルトの名無しさん:2008/07/05(土) 09:53:45
>>985
使わなくてもいい方法を一度考えてから質問しようぜ
988デフォルトの名無しさん:2008/07/05(土) 10:06:30
>>987
mutexしたくないので使わないと無理です
989デフォルトの名無しさん:2008/07/05(土) 10:30:30
まさか、グローバル変数だけで作ってるのか?
990デフォルトの名無しさん:2008/07/05(土) 10:43:59
うん
991デフォルトの名無しさん:2008/07/05(土) 10:44:54
>>990
NT系列のコーディング規約でそうなってるの
どうすればいいの?
992デフォルトの名無しさん:2008/07/05(土) 11:44:32
グローバル変数の使用が強制されたコーディング規則だと・・・

もちろん釣りだよな。
993デフォルトの名無しさん:2008/07/05(土) 11:46:05
今人気急上昇中の組み込み系かもしれない
994デフォルトの名無しさん:2008/07/05(土) 11:54:24
>>992
いやまじなんですよ本当に
コーディングルールの
項4.5.1に、共有データはグローバル変数として
定義し他者が利用しやすいように記述すること
って載ってるんですよ

本当に助けてくださいまじで困ってます。
もう吊ろうかな3日も寝てなくて頭おかしくなってきたし
995デフォルトの名無しさん:2008/07/05(土) 12:11:23
>>994
TLSにデータを置いたら、他のスレッドからアクセスできなくなるから共有にならないけどいいの?
996デフォルトの名無しさん:2008/07/05(土) 12:14:24
>994
共有データって書いてあるじゃん。
共有データじゃないものには適用するな。
997デフォルトの名無しさん:2008/07/05(土) 12:23:00
>>994
今やってるところは個別のスレッドで
データ作って処理するところなんですよ
規約でグローバル変数は共有する場合だけ
だから使うなって言われたけどどうすればいいか
わからないし

998デフォルトの名無しさん:2008/07/05(土) 12:30:35
>>997
使うなっていわれたんだから使わないでOK
グローバル変数は使わないのが正道
999デフォルトの名無しさん:2008/07/05(土) 12:37:26
>>997
個別のスレッドでデータ造って処理するんだから、他のスレッドと
共有なんかしなくていいんだろ。

だから、グローバルを使わなくていいんだし、素直に >>986 でい
いだろ。

スレッドローカルデータがどうのこうのの前に、日本語理解力と
コミュニケーション能力を何とかした方がいいと思うよ。
1000デフォルトの名無しさん:2008/07/05(土) 12:40:07
時間切れとなりました
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。