删除此安全保护互斥示例中的定义

| -编辑-我不能尝试自动柜员机,但今晚会。我想也许typedef可以用来保存mut并可以用来声明var。但是我最初的想法是typedef不能很好地与模板配合使用,所以我今晚必须检查一下(目前,要上课) 我正在查看下面显示的这段代码,我想知道如果不使用定义怎么可能实现。 由于我无法编译代码(我目前未安装任何互斥锁/多线程库),因此我只会看一下代码并仔细考虑。 似乎可以通过继承模板类来完全实现“ 0”。现在的问题是
PROTECTED_MEMBER
。它使用带有##的名称来创建变量。这不是什么大问题,因为我们创建了一个类,该类使用
()
运算符保存该变量,以使其作为函数出现。但是访问
is_held()
问题,因为我不想传入not4ѭ或
mut_
。 我的直截了当地说,开箱即用的想法是可以解决这个问题,而无需定义,也不必传入每个变量,函数ptr或引用。我将允许所有人作弊并使用c ++ 0x功能。
template<typename Mutex>
class TestableMutex {
public:
     void lock()      {  m.lock();  id = this_thread::get_id();  }
     void unlock()    {  id = 0;  m.unlock();  }
     bool try_lock()  {  bool b = m.try_lock();
                 if( b ) id = this_thread::get_id();
                 return b;  }
     bool is_held()    { return id == this_thread::get_id(); }
private:
     Mutex m;
     atomic<thread::id> id;
     // for recursive mutexes, add a count
};

#define PROTECTED_WITH(MutType)  \\
     public:    void    lock()        {  mut_.lock();  } \\
     public:    bool    try_lock()    {  return mut_.try_lock();  } \\
     public:    void    unlock()      {  mut_.unlock();  } \\
     private:    TestableMutex<MutType> mut_;
#define PROTECTED_MEMBER(Type,name) \\
     public:    Type&   name()        { assert(mut_.is_held()); return name##_; } \\
     private:    Type   name##_;

struct MyData {
     PROTECTED_WITH( some_mutex_type );
     PROTECTED_MEMBER( vector<int>, v );
     PROTECTED_MEMBER( Widget*, w );
};
    
已邀请:
        您可以使用包含“ 7”声明的显式专门化来列出受互斥对象保护的对象。然后使用基类通过
operator->
将访问“传递”给用户,因此
object->member
object
不是指针)执行互斥量声明。 这比说起来容易:
// Imagine that the members of this class must be locked by the mutex.
class a : public expose_locked_by_arrow< a > {
protected:
    int i;
    void f();
};

// Declare which members are conditionally locked. Pretty simple and idiomatic.
template<>
struct member_expose< a > : a {
    using a::i;
    using a::f;
};

#include <iostream>

// Access mutex-locked members with ->
int main() {
        a x;
        x->i = 5;
        a const y( x );
        std::cout << y->i << \'\\n\';
}
库代码:
// This template is specialized for each mutex protection client.
template< class >
struct member_expose;

// Base class provides mutex; parameter is derived class (CRTP).
template< class c >
struct expose_locked_by_arrow {
    member_expose< c > *
    operator->() {
        assert ( expose_lock_mutex.is_held() );
        return static_cast< member_expose< c > * >( this );
    }

    member_expose< c > const *
    operator->() const {
        assert ( expose_lock_mutex.is_held() );
        return static_cast< member_expose< c > const * >( this );
    }

    expose_locked_by_arrow( mutex const &m = mutex() )
        : expose_lock_mutex( m ) {}

protected:
    mutex expose_lock_mutex;
};
看到它运行。     
        ѭ13并没有提供任何保护,相反,它们只是减少了您必须进行的键入操作的数量(反过来,它们确保所有“ protected”成员都具有正确的代码) 。 我知道,没有一种方法可以避免必须将检查放入每个getter函数中并锁定整个对象,因为它们将返回对存储在受保护对象中的数据的引用。 但是,如果它们都可以按值返回(或根本不返回任何值),那么您可以使用一个使用代理对象锁定所有内容的容器,如下所示(这可能做得更好,我只是很快将它们一起砍掉了):
#include <iostream>

struct Mutex
{
    void lock()
    {
        std::cout << \"Mutex::lock\" << std::endl;
    }

    void unlock()
    {
        std::cout << \"Mutex::unlock\" << std::endl;
    }
};

template <class Object>
class ThreadSafeObject
{
    mutable Mutex  d_mutex;
    Object         d_object;

  public:
    struct Proxy
    {
        mutable Mutex *d_mutex;
        Object        *d_object;

        Proxy(Mutex *mutex, Object *object)
        : d_mutex(mutex)
        , d_object(object)
        {
            d_mutex->lock();
        }

        Proxy(const Proxy& proxy)
        : d_mutex(proxy.d_mutex)
        , d_object(proxy.d_object)
        {
            proxy.d_mutex = NULL;
        }

        ~Proxy()
        {
            if (d_mutex)
            {
                d_mutex->unlock();
            }
        }

        Object *operator->()
        {
            return d_object;
        }
    };

    struct ConstProxy
    {
        mutable Mutex *d_mutex;
        const Object  *d_object;

        ConstProxy(Mutex *mutex, const Object *object)
        : d_mutex(mutex)
        , d_object(object)
        {
            d_mutex->lock();
        }

        ConstProxy(const ConstProxy& proxy)
        : d_mutex(proxy.d_mutex)
        , d_object(proxy.d_object)
        {
            proxy.d_mutex = NULL;
        }

        ~ConstProxy()
        {
            if (d_mutex)
            {
                d_mutex->unlock();
            }
        }

        const Object *operator->() const
        {
            return d_object;
        }
    };

    Proxy operator->()
    {
        return Proxy(&d_mutex, &d_object);
    }

    ConstProxy operator->() const
    {
        return ConstProxy(&d_mutex, &d_object);
    }
};

struct Foo
{
    void foo()
    {
        std::cout << \"Foo::foo\" << std::endl;
    }
};

int main()
{
    ThreadSafeObject<Foo> myFoo;
    myFoo->foo();
    return 0;
}
它使用operator->()技巧(当operator->不返回指针类型时,编译器将继续对返回的值调用operator->,直到最终返回常规指针类型为止)并给出以下输出:
Mutex::lock
Foo::foo
Mutex::unlock
通常来说,需要多个线程使用的对象不应像这样暴露其内部,让它接受参数并使用其内部值对它们进行操作会更安全。     

要回复问题请先登录注册