私が意図したように、コードのこの部分が動作しないことが判明:私はcv.wait_until
コールで1秒間待ってから繰り返すコードを期待条件変数と#pragmaパックのバグ
#pragma pack(push, 1)
class myclass {
protected:
bool mycrasher[1]; // with mycrasher[4] it works!
std::mutex mtx;
std::condition_variable cv;
void thread_func() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::chrono::milliseconds timeout(1000);
std::unique_lock<std::mutex> l(mtx, std::defer_lock);
while (true) {
auto now = std::chrono::system_clock::now();
l.lock();
while (true) {
std::cout << "Waiting..." << std::endl;
auto result = cv.wait_until(l, now + timeout);
std::cout << "Timed out..." << std::endl;
if (result == std::cv_status::timeout)
break;
}
l.unlock();
}
}
public:
myclass() {
std::lock_guard<std::mutex> l(mtx);
std::thread *t = new std::thread(&myclass::thread_func, this);
t->detach();
};
void start() {
std::cout << "myclass started." << std::endl;
std::cout << "sizeof(std::mutex) = " << sizeof(std::mutex) << std::endl;
std::cout << "sizeof(std::condition_variable) = " << sizeof(std::condition_variable) << std::endl;
}
};
#pragma pack(pop)
int main() {
myclass x;
x.start();
std::this_thread::sleep_for(std::chrono::seconds(60));
}
が、単にコールにハングアップします。私がmutexとCVをパックしているので、#pragma
ディレクティブを削除すると、(直感的に)問題がなくなります。 pragma
の有無にかかわらず
myclass started.
sizeof(std::mutex) = 40
sizeof(std::condition_variable) = 48
をので、梱包は本当の問題ではないようだ。私はこのコードを実行するときしかし、私が取得します。
さらに、mycrasher
変数を4バイト境界に揃えると、問題が消えてしまうことも発見しました。同様に、std::condition_variable cv
宣言の後に変数を移動すると、問題は消えますが、std::mutex mtx
とstd::condition_variable cv
の間で移動すると、それでも問題は解決しません。
なぜCVが正しく整列されていないときにcv.wait_until
コールでスニペットがハングするのですか?パフォーマンスヒットが予想されますが、プレーストールではありません。
Debian 8システムでg ++ 4.9.2およびg ++ 6.3で再現されました。
'#pragma pack'はあなたの構造体にのみ使用され、あなたの構造体で使用するものはありません。奇数アドレスにmutexや条件変数を設定することはできないようです。おそらく、あなたがなぜ* #pragma packを使用したいのか、なぜそれを使って解決しようとしているのか、私たちはあなたにその問題を手伝うことができますか? –
@Someprogrammerdudeありがとう、私はそれを発見しました。私は*なぜそれが働くのを理解したかったのですか?これはメモリを大量に消費するアプリケーションの一部でなければならないため、パックされたデータはすべてのバイトを圧縮することを目的としています。 – xmas79
@ xmas79:それは逆行する可能性があります。すべてのバイトを圧縮すると、無関係なデータを同じキャッシュラインに置くことができます。これは早すぎる最適化の別のケースのように見えます。 – MSalters