Несколько CResourceUsers используя один CResource


  • Мне нужно несколько CResourceUsers поделиться один экземпляр CResource.
  • Я хочу, чтобы инстанцировать CResource только если по крайней мере один CResourceUser существует.
  • CResource это не синглтон по дизайну, могут существовать другие пользователи CResource
  • В C++98 используется
  • Только решения Windows
  • CResource методы потокобезопасны

Я начинала с простого

CResource & CResourceUser::Resource() const
{
    static CResource resource("resource");
    return resource;
}

Который должен быть использован такой:

CResourceUser::CResourceUser()
{
    std::cout << "+++ CResourceUser" << std::endl;
    Resource().DoSomething();
}

Но это, кажется, не быть резьбой-безопасный.

Так что я пришел с немного сложным решением:

Synchronisation.h:

#include <Windows.h>

namespace Synchronization {

class CriticalSection 
{ 
    friend class Lock; 

    public: CriticalSection () 
    { 
        ::InitializeCriticalSection (&_critSect); 
    } 

    ~CriticalSection () 
    { 
        ::DeleteCriticalSection (&_critSect);
    } 

    private: CRITICAL_SECTION _critSect; 
};


class Lock 
{ 
    public: Lock (CriticalSection & critSect) : _section (critSect) 
    { 
        ::EnterCriticalSection (&_section._critSect); 
    } 

    ~Lock () 
    { 
        ::LeaveCriticalSection (&_section._critSect); 
    } 

    private: CriticalSection & _section; 
};

}

#include <iostream>
#include <Windows.h>

Остальной код теперь выглядит немного лучше:

#include <iostream>
#include "Synchronization.h"

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

class CResource
{
public:
    CResource(const std::string &_name)
        :name(_name)
    {
    }

    ~CResource()
    {
    }

    void DoSomething()
    {
        std::cout << "Something!" << std::endl;
    }
private:
    const std::string name;
};

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

class CResourceUser
{
public:
    CResourceUser()
    {
        Resource().DoSomething();
    }
private:
    CResource & Resource() const
    {
        Synchronization::Lock resourceInitGuard(s_csResourceInit);
        static CResource resource("resource");
        return resource;
    }
    static Synchronization::CriticalSection s_csResourceInit;
};

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

Synchronization::CriticalSection CResourceUser::s_csResourceInit;

int main()
{
    CResourceUser user1;
    CResourceUser user2;
    CResourceUser user3;
    return 0;
}

Так что сейчас я в порядке с кодом, он более читабельный, чем в предыдущей версии, и это, кажется, работает, как ожидалось.

Остается главный вопрос: код правильный?

Пожалуйста, игнорируйте венгерская нотация.



105
2
задан 12 апреля 2018 в 01:04 Источник Поделиться
Комментарии