3

同時に使用できるかどうかに関係なく、新しいクラスを作成するとします。明らかに、同時に呼び出される可能性があるすべてのものをロックしたくはありません。これに対処する 1 つの方法は、ロックを指定するミックスインによるパラメーター化です。

template<class Locking>
struct foo : private Locking {
    void bar() {
        Locking::read_lock();
        // Do something.
        Locking::read_unlock();
    }
};

Lockingマルチスレッドの場合は実際にロックするクラスでインスタンス化し、他の場合はノーオペレーションを行うクラスでインスタンス化します (うまくいけば、コンパイラは呼び出しを最適化します)。

ここで、ロックの代わりにソフトウェア トランザクション メモリを使用してこれを行いたいとします。N3919 (またはgcc 前駆体)を見ると、考え方が異なります。などの呼び出しはありません。

transaction_start();

transaction_end();

代わりに、次のような関数指定子があります

void bar() transaction_safe;

およびブロック指定子のような

transaction { /* body */ }

後者が前者を呼び出すという厳格なルールがあり、そのように見えるものはミックスインで使用できません。

これを行うにはどうすればよいですか (プリプロセッサを使用せずに)。また、STM の主な利点の 1 つはコンポーザビリティbarですが、トランザクション可能であることをインスタンス化に反映させる方法はないようです。

4

1 に答える 1

1

同様に、ラムダを使用すると、次のようなことができるようです。

template<class Transaction>
struct foo {
    void bar() {
        Transaction::run([](){ /* Do something. */ });
    }
};

2つの実装で

template<typename F>
void TransactionNone::run(F f) { f(); }

template<typename F>
void TransactionReal::run(F f) { transaction{ f(); } }

属性については、

トランザクション アンセーフでない関数は、トランザクション セーフです。

そのため、そのキーワードを省略して、コンパイラ/リンカーにその仕事をさせてもよいようです。

于 2016-08-09T20:34:40.297 に答える