синхронизированные классы
От: Леший Россия  
Дата: 30.05.03 10:15
Оценка: 8 (1)
Хочется придумать какую-нибудь базу для создания классов, вызовы функций в которых синхронизированы автоматом.
Что-нибудь вроде автоматического вызова EnterCriticalSection() в начале метода и LeaveCriticalSection() в конце.

Можно ли это как-нибудь сделать красиво? Скажем, в виде базового класса, шаблона или чего-нибудь подобного?
(#define не предлагать! )
Re: синхронизированные классы
От: Bell Россия  
Дата: 30.05.03 10:25
Оценка: +1
Здравствуйте, Леший, Вы писали:

Л>Хочется придумать какую-нибудь базу для создания классов, вызовы функций в которых синхронизированы автоматом.

Л>Что-нибудь вроде автоматического вызова EnterCriticalSection() в начале метода и LeaveCriticalSection() в конце.

Л>Можно ли это как-нибудь сделать красиво? Скажем, в виде базового класса, шаблона или чего-нибудь подобного?

Л>(#define не предлагать! )

В начале каждой такой функции создавать автоматический объект, который в своем клнструкторе будет вызывать EnterCriticalSection(), а в деструкторе — LeaveCriticalSection()

Правда код для этого (одну строчку) все равно писать надо...
Любите книгу — источник знаний (с) М.Горький
Re: синхронизированные классы
От: MaximE Великобритания  
Дата: 30.05.03 11:06
Оценка:
Здравствуйте, Леший, Вы писали:

Л>Хочется придумать какую-нибудь базу для создания классов, вызовы функций в которых синхронизированы автоматом.

Л>Что-нибудь вроде автоматического вызова EnterCriticalSection() в начале метода и LeaveCriticalSection() в конце.

Легко.

Вот это рачитано на применение с boost::thread::mutex, но легко переделать и под нативную CRITICAL_SECTION.

////////////////////////////////////////////////////////////////////////////////////////////////
// mutex_protected.hpp

#pragma once

#include <iosfwd>

////////////////////////////////////////////////////////////////////////////////////////////////

namespace util
{

////////////////////////////////////////////////////////////////////////////////////////////////

template<class T, class mutex>
class mutex_protected
{
    class locker
    {
    public:
        locker(volatile const mutex_protected* p)
            :    p_(p)
            ,    l_(*p_->m_, false)
        {}

        locker(const locker& other) // copy-constructable
            :    p_(other.p_)
            ,    l_(*p_->m_, false)
        {}

        T* operator->()
        {
            l_.lock();
            return p_->t_;
        }

    private:
        locker& operator=(const locker&); // not assignable

        volatile const mutex_protected* p_;
        typename mutex::scoped_lock l_;
    };

    friend class locker;

public:
    mutex_protected(T& t, mutex& m)
        :    t_(&t)
        ,    m_(&m)
    {}

public:
    locker operator->() volatile const { return this; }
    T* get() const { return t_; }

private:
    T* t_;
    mutex* m_;
};

////////////////////////////////////////////////////////////////////////////////////////////////

template<class mutex, mutex* m>
class mutex_manipulator
{
public:
    mutex_manipulator()
        :    l_(*m)
    {}

private:
    typename mutex::scoped_lock l_;
};

template<class c, class t, class mutex, mutex* m>
inline std::basic_ostream<c, t>& operator<<(std::basic_ostream<c, t>& s,
                                            const mutex_manipulator<mutex, m>&)
{
    return s;
}

////////////////////////////////////////////////////////////////////////////////////////////////

} // namespace util

////////////////////////////////////////////////////////////////////////////////////////////////


Пример использования:


extern boost::mutex clog_mutex__;
typedef util::mutex_manipulator<boost::mutex, &clog_mutex__> clog_mutex;
#define CLOG_T_MT clog_t << clog_mutex()
#define LOG_LINE_END _T("\r\n")

//

class simulator_impl : public ref_counted_impl<simulator>, private conductor_mediator
{
public:
    simulator_impl()
        :    conductors_mt_(conductors_, mutex_conductors_)
    {}

    // ...

private: // conductor_mediator
    void on_start(conductor* c) volatile
    {
        CLOG_T_MT << c << _T("Started.") << LOG_LINE_END;
    }

    void on_stop(conductor* c) volatile
    {
        // автоматом лочим на время вызова
        conductors_mt_->erase(to_server_id(*c));

        CLOG_T_MT << c << _T("Stopped.") << LOG_LINE_END;
    }

    void on_error(conductor* c, const string_t& desc) volatile
    {
        conductors_mt_->erase(to_server_id(*c));

        CLOG_T_MT << c << _T("Failed : ") << desc << _T(".") << LOG_LINE_END;
    }

private:
    typedef map<server_id, conductor_p> conductors;
    conductors conductors_;
    boost::mutex mutex_conductors_;
    volatile util::mutex_protected<conductors, boost::mutex> conductors_mt_;
Re: универсальный wrapper
От: jazzer Россия Skype: enerjazzer
Дата: 30.05.03 11:49
Оценка:
Здравствуйте, Леший, Вы писали:

Л>Хочется придумать какую-нибудь базу для создания классов, вызовы функций в которых синхронизированы автоматом.

Л>Что-нибудь вроде автоматического вызова EnterCriticalSection() в начале метода и LeaveCriticalSection() в конце. :???:

Л>Можно ли это как-нибудь сделать красиво? Скажем, в виде базового класса, шаблона или чего-нибудь подобного?

Л>(#define не предлагать! ;) )

Лучше всего запроксить объект с помощью сабжа.
См., например, дискуссию здесь
Автор: jazzer
Дата: 13.11.02
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: синхронизированные классы
От: MaximE Великобритания  
Дата: 31.05.03 15:47
Оценка:
Здравствуйте, MaximE, Вы писали:

Более ясный пример:
// experiment.cpp

#include <iostream>

#include <boost/thread/detail/config.hpp>
#include <boost/thread.hpp>
#include <libs/thread/src/timeconv.inl>
#pragma comment(lib, "boost_threadd.lib")


#include "mutex_protected.hpp"

struct some
{
    void say_a()
    {
        std::cout << "starting saying a...\n";

        boost::xtime delay;
        to_time(1000, delay);
        boost::thread().sleep(delay);

        std::cout << "end saying a.\n";
    }

    void say_b()
    {
        std::cout << "starting saying b...\n";

        boost::xtime delay;
        to_time(1000, delay);
        boost::thread().sleep(delay);

        std::cout << "end saying b.\n";
    }
};

// сереализуем доступ к этому объекту
some s;
// посредством этого мьютекса
boost::mutex m;
// и этого proxy-объекта
util::mutex_protected<some, boost::mutex> thread_safe_s(s, m);

// очевидно
boost::mutex cout_mutex__;
typedef util::mutex_manipulator<boost::mutex, &cout_mutex__> cout_mutex;

void thread_1()
{
    std::cout << cout_mutex() << "started thread 1.\n";

    for (int n(0x10); n--;)
        //s.say_a();
        thread_safe_s->say_a();

    std::cout << cout_mutex() << "ended thread 1.\n";
}

void thread_2()
{
    std::cout << cout_mutex() << "started thread 2.\n";

    for (int n(0x10); n--;)
        //s.say_b();
        thread_safe_s->say_b();

    std::cout << cout_mutex() << "ended thread 2.\n";
}

int main()
{
    boost::thread_group threads;

    threads.create_thread(&thread_1);
    threads.create_thread(&thread_2);

    threads.join_all();
}

started thread 1.
starting saying a...
started thread 2.
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
end saying b.
starting saying a...
end saying a.
starting saying b...
ended thread 1.
end saying b.
ended thread 2.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.