Вот написал маленький класс и думаю не изобрел ли я велосипед (в который раз... )
Как его обозвать даже не знаю, и как описать тоже, но попробую.
Итак, имеется у нас объект. Его можно Open и Release (по аналогии с mutex'oм). Открыть его можно только N раз, как только все его освободили то у нас устанавливается событие. Как только его кто-то открыл тоже устанавливается событие, но другое. Пока писал эти строки, пришло в голову, что N раз это не принципиально. Вот вообщем-то и все.
Можно пользовать в многопоточном приложении (для этого и задумывался), но есть сумнения. может вы, уважаемый алл, подскажите (выделенно жирным).
Здравствуйте BlackBox, Вы писали:
BB>Привет всем!
BB> Вот написал маленький класс и думаю не изобрел ли я велосипед (в который раз... )
BB> Как его обозвать даже не знаю, и как описать тоже, но попробую.
BB>Итак, имеется у нас объект. Его можно Open и Release (по аналогии с mutex'oм). Открыть его можно только N раз, как только все его освободили то у нас устанавливается событие. Как только его кто-то открыл тоже устанавливается событие, но другое. Пока писал эти строки, пришло в голову, что N раз это не принципиально. Вот вообщем-то и все. BB>Можно пользовать в многопоточном приложении (для этого и задумывался), но есть сумнения. может вы, уважаемый алл, подскажите (выделенно жирным).
[покоцано]
BB>Принимается любая критика по поводу кода.
Любую критику, говорите, принимаете? Итак:
1. Уберите от греха __fastcall. Тогда класс можно будет использовать в средах, отличных от Borland C++ Builder .
2. По коду (убрал все __fastcall, ну и так, замечания по ходу):
// - header ---class CBlackMutex
{
int Size;
long ResCount;
HANDLE hEvents[2];
public:
CBlackMutex(int sz=5); // лучше unsigned int
~CBlackMutex();
bool Open();
bool Release();
HANDLE GetEmpty(){return hEvents[1];}
HANDLE GetOpened(){return hEvents[0];}
};
// - code ---
CBlackMutex::CBlackMutex(unsigned int sz) // добавил unsigned
{
// если unsigned, то проверку можно убрать
// if (sz <= 0) sz = 1;
Size = sz;
ResCount = 0;
hEvents[0] = hEvents[1] = NULL;
hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
}
CBlackMutex::~CBlackMutex()
{
// Тут я немножко подрезал код... И так все ясно, без != NULL
// if (hEvents[0] != NULL) CloseHandle(hEvents[0]);
// if (hEvents[1] != NULL) CloseHandle(hEvents[1]);if ( hEvents[0] ) CloseHandle(hEvents[0]);
if ( hEvents[1] ) CloseHandle(hEvents[1]);
// это зачем???
// hEvents[0] = hEvents[1] = NULL;
}
bool CBlackMutex::Open()
{
if (InterlockedExchangeAdd(&ResCount, 0) == Size) return false;
if (InterlockedExchangeAdd(&ResCount, 0) == 0)
{
SetEvent(hEvents[0]); // нет проверки ошибок...
}
InterlockedExchangeAdd(&ResCount, 1); // multithreading ++ :Dreturn true;
}
bool CBlackMutex::Release()
{
if (InterlockedExchangeAdd(&ResCount, 0) == 0) return false;
InterlockedExchangeAdd(&ResCount, -1); // multithreading -- :Dif (InterlockedExchangeAdd(&ResCount, 0) == 0)
{
SetEvent(hEvents[1]); // нет проверки ошибок...
}
return true;
}
Здравствуйте BlackBox, Вы писали:
BB>Привет всем!
BB> Вот написал маленький класс и думаю не изобрел ли я велосипед (в который раз... )
BB> Как его обозвать даже не знаю, и как описать тоже, но попробую.
BB>Итак, имеется у нас объект. Его можно Open и Release (по аналогии с mutex'oм). Открыть его можно только N раз, как только все его освободили то у нас устанавливается событие. Как только его кто-то открыл тоже устанавливается событие, но другое. Пока писал эти строки, пришло в голову, что N раз это не принципиально. Вот вообщем-то и все. BB>Можно пользовать в многопоточном приложении (для этого и задумывался), но есть сумнения. может вы, уважаемый алл, подскажите (выделенно жирным).
BB>
Здравствуйте Flamer, Вы писали:
F>Здравствуйте BlackBox, Вы писали:
[skip]
F>1. Уберите от греха __fastcall. Тогда класс можно будет использовать в средах, отличных от Borland C++ Builder .
ok
[skip] F>CBlackMutex::CBlackMutex(unsigned int sz) // добавил unsigned F>{ F> // если unsigned, то проверку можно убрать F>// if (sz <= 0) sz = 1;
Спасибо, как то не думал об этом. F> Size = sz; F> ResCount = 0; F> hEvents[0] = hEvents[1] = NULL; F> hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL); F> hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL); F>}
F>CBlackMutex::~CBlackMutex() F>{ F>// Тут я немножко подрезал код... И так все ясно, без != NULL
Дело привычки F>// if (hEvents[0] != NULL) CloseHandle(hEvents[0]); F>// if (hEvents[1] != NULL) CloseHandle(hEvents[1]);
F> if ( hEvents[0] ) CloseHandle(hEvents[0]); F> if ( hEvents[1] ) CloseHandle(hEvents[1]);
F>// это зачем??? F>// hEvents[0] = hEvents[1] = NULL;
Это у меня параноя такая. Зачем делаю сам не знаю. Но делаю... F>}
Здравствуйте Алекс, Вы писали:
А>Здравствуйте BlackBox, Вы писали:
[skip]
А>я не буду оценивать нужность класса и его функционал, а только попридираюсь к коду. ок? А>1. нет конструктора по умолчанию — неудобно
CBlackMutex(int sz=5); // <--- не оно?
А>2. зачем нужно А>
А>hEvents[0] = hEvents[1] = NULL;
А>
А>в деструкторе А>3. хачем для чтения ResCount использовать InterlockedExchangeAdd(&ResCount, 0)
чтобы получить значение не изменяя его.
[skip] А>6. никак не пойму внутреннего смысла функций А>
Здравствуйте Flamer, Вы писали:
F>Здравствуйте BlackBox, Вы писали:
BB>>Привет всем!
BB>> Вот написал маленький класс и думаю не изобрел ли я велосипед (в который раз... )
BB>> Как его обозвать даже не знаю, и как описать тоже, но попробую.
BB>>Итак, имеется у нас объект. Его можно Open и Release (по аналогии с mutex'oм). Открыть его можно только N раз, как только все его освободили то у нас устанавливается событие. Как только его кто-то открыл тоже устанавливается событие, но другое. Пока писал эти строки, пришло в голову, что N раз это не принципиально. Вот вообщем-то и все. BB>>Можно пользовать в многопоточном приложении (для этого и задумывался), но есть сумнения. может вы, уважаемый алл, подскажите (выделенно жирным).
F>[покоцано]
BB>>Принимается любая критика по поводу кода.
F>Любую критику, говорите, принимаете? Итак:
F>1. Уберите от греха __fastcall. Тогда класс можно будет использовать в средах, отличных от Borland C++ Builder .
F>2. По коду (убрал все __fastcall, ну и так, замечания по ходу):
F>
F>// - header ---
F>class CBlackMutex
F>{
F> int Size;
F> long ResCount;
F> HANDLE hEvents[2];
F>public:
F> CBlackMutex(int sz=5); // лучше unsigned int
F> ~CBlackMutex();
F> bool Open();
F> bool Release();
F> HANDLE GetEmpty(){return hEvents[1];}
F> HANDLE GetOpened(){return hEvents[0];}
F>};
F>// - code ---
F>CBlackMutex::CBlackMutex(unsigned int sz) // добавил unsigned
F>{
F> // если unsigned, то проверку можно убрать
F>// if (sz <= 0) sz = 1;
F> Size = sz;
F> ResCount = 0;
F> hEvents[0] = hEvents[1] = NULL;
F> hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
F> hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
F>}
F>CBlackMutex::~CBlackMutex()
F>{
F>// Тут я немножко подрезал код... И так все ясно, без != NULL
F>// if (hEvents[0] != NULL) CloseHandle(hEvents[0]);
F>// if (hEvents[1] != NULL) CloseHandle(hEvents[1]);
F> if ( hEvents[0] ) CloseHandle(hEvents[0]);
F> if ( hEvents[1] ) CloseHandle(hEvents[1]);
F>// это зачем???
F>// hEvents[0] = hEvents[1] = NULL;
F>}
F>bool CBlackMutex::Open()
F>{
F> if (InterlockedExchangeAdd(&ResCount, 0) == Size) return false;
F> if (InterlockedExchangeAdd(&ResCount, 0) == 0)
F> {
F> SetEvent(hEvents[0]); // нет проверки ошибок...
F> }
F> InterlockedExchangeAdd(&ResCount, 1); // multithreading ++ :D
F> return true;
F>}
F>bool CBlackMutex::Release()
F>{
F> if (InterlockedExchangeAdd(&ResCount, 0) == 0) return false;
F> InterlockedExchangeAdd(&ResCount, -1); // multithreading -- :D
F> if (InterlockedExchangeAdd(&ResCount, 0) == 0)
F> {
F> SetEvent(hEvents[1]); // нет проверки ошибок...
F> }
F> return true;
F>}
F>
F>Вот, в общем... Сами просили
И я тут поучаствую
CBlackMutex::~CBlackMutex()
{
// Я бы сделал во как
if ( hEvents[0] != INVALID_HANDLE_VALUE) CloseHandle(hEvents[0]);
if ( hEvents[1] != INVALID_HANDLE_VALUE ) CloseHandle(hEvents[1]);
hEvents[0] = hEvents[1] = INVALID_HANDLE_VALUE;
}
Здравствуйте BlackBox, Вы писали:
BB>Здравствуйте Алекс, Вы писали:
А>>Здравствуйте BlackBox, Вы писали:
BB>[skip]
А>>я не буду оценивать нужность класса и его функционал, а только попридираюсь к коду. ок? А>>1. нет конструктора по умолчанию — неудобно BB>
BB>CBlackMutex(int sz=5); // <--- не оно?
BB>
А>>2. зачем нужно А>>
А>>hEvents[0] = hEvents[1] = NULL;
А>>
А>>в деструкторе А>>3. хачем для чтения ResCount использовать InterlockedExchangeAdd(&ResCount, 0) BB>чтобы получить значение не изменяя его. BB>[skip] А>>6. никак не пойму внутреннего смысла функций А>>
[skip]
AS>А зачем было hEvents[...] обьявлять как private, если потом так спокойно AS>их отдавать?
Да, конечно, их можно сделать и public, но как лучше всего сделать в многопоточной среде??
Или и так уже все нормально, и осталось только исправить private на public.
Здравствуйте Alex Smirnov, Вы писали:
AS>Здравствуйте Flamer, Вы писали:
F>>Здравствуйте BlackBox, Вы писали:
BB>>>Привет всем!
BB>>> Вот написал маленький класс и думаю не изобрел ли я велосипед (в который раз... )
BB>>> Как его обозвать даже не знаю, и как описать тоже, но попробую.
BB>>>Итак, имеется у нас объект. Его можно Open и Release (по аналогии с mutex'oм). Открыть его можно только N раз, как только все его освободили то у нас устанавливается событие. Как только его кто-то открыл тоже устанавливается событие, но другое. Пока писал эти строки, пришло в голову, что N раз это не принципиально. Вот вообщем-то и все. BB>>>Можно пользовать в многопоточном приложении (для этого и задумывался), но есть сумнения. может вы, уважаемый алл, подскажите (выделенно жирным).
F>>[покоцано]
BB>>>Принимается любая критика по поводу кода.
F>>Любую критику, говорите, принимаете? Итак:
F>>1. Уберите от греха __fastcall. Тогда класс можно будет использовать в средах, отличных от Borland C++ Builder .
F>>2. По коду (убрал все __fastcall, ну и так, замечания по ходу):
F>>
F>>// - header ---
F>>class CBlackMutex
F>>{
F>> int Size;
F>> long ResCount;
F>> HANDLE hEvents[2];
F>>public:
F>> CBlackMutex(int sz=5); // лучше unsigned int
F>> ~CBlackMutex();
F>> bool Open();
F>> bool Release();
F>> HANDLE GetEmpty(){return hEvents[1];}
F>> HANDLE GetOpened(){return hEvents[0];}
F>>};
F>>// - code ---
F>>CBlackMutex::CBlackMutex(unsigned int sz) // добавил unsigned
F>>{
F>> // если unsigned, то проверку можно убрать
F>>// if (sz <= 0) sz = 1;
F>> Size = sz;
F>> ResCount = 0;
F>> hEvents[0] = hEvents[1] = NULL;
F>> hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
F>> hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
F>>}
F>>CBlackMutex::~CBlackMutex()
F>>{
F>>// Тут я немножко подрезал код... И так все ясно, без != NULL
F>>// if (hEvents[0] != NULL) CloseHandle(hEvents[0]);
F>>// if (hEvents[1] != NULL) CloseHandle(hEvents[1]);
F>> if ( hEvents[0] ) CloseHandle(hEvents[0]);
F>> if ( hEvents[1] ) CloseHandle(hEvents[1]);
F>>// это зачем???
F>>// hEvents[0] = hEvents[1] = NULL;
F>>}
F>>bool CBlackMutex::Open()
F>>{
F>> if (InterlockedExchangeAdd(&ResCount, 0) == Size) return false;
F>> if (InterlockedExchangeAdd(&ResCount, 0) == 0)
F>> {
F>> SetEvent(hEvents[0]); // нет проверки ошибок...
F>> }
F>> InterlockedExchangeAdd(&ResCount, 1); // multithreading ++ :D
F>> return true;
F>>}
F>>bool CBlackMutex::Release()
F>>{
F>> if (InterlockedExchangeAdd(&ResCount, 0) == 0) return false;
F>> InterlockedExchangeAdd(&ResCount, -1); // multithreading -- :D
F>> if (InterlockedExchangeAdd(&ResCount, 0) == 0)
F>> {
F>> SetEvent(hEvents[1]); // нет проверки ошибок...
F>> }
F>> return true;
F>>}
F>>
F>>Вот, в общем... Сами просили
AS>И я тут поучаствую AS>
AS>CBlackMutex::~CBlackMutex()
AS>{
AS>// Я бы сделал во как
AS> if ( hEvents[0] != INVALID_HANDLE_VALUE) CloseHandle(hEvents[0]);
AS> if ( hEvents[1] != INVALID_HANDLE_VALUE ) CloseHandle(hEvents[1]);
AS> hEvents[0] = hEvents[1] = INVALID_HANDLE_VALUE;
AS>}
AS>
ну здесь ты не прав, т.к. в случае ошибки CreateEvent() возвращает NULL, а не INVALID_HANDLE_VALUE.
Здравствуйте BlackBox, Вы писали:
BB>Здравствуйте Алекс, Вы писали:
А>>Здравствуйте BlackBox, Вы писали:
BB>[skip]
А>>я не буду оценивать нужность класса и его функционал, а только попридираюсь к коду. ок? А>>1. нет конструктора по умолчанию — неудобно BB>
BB>CBlackMutex(int sz=5); // <--- не оно?
BB>
сори, не заметил
BB>чтобы получить значение не изменяя его.
Здравствуйте Алекс, Вы писали:
А>Здравствуйте Alex Smirnov, Вы писали:
AS>>Здравствуйте Flamer, Вы писали:
F>>>Здравствуйте BlackBox, Вы писали:
BB>>>>Привет всем!
BB>>>> Вот написал маленький класс и думаю не изобрел ли я велосипед (в который раз... )
BB>>>> Как его обозвать даже не знаю, и как описать тоже, но попробую.
BB>>>>Итак, имеется у нас объект. Его можно Open и Release (по аналогии с mutex'oм). Открыть его можно только N раз, как только все его освободили то у нас устанавливается событие. Как только его кто-то открыл тоже устанавливается событие, но другое. Пока писал эти строки, пришло в голову, что N раз это не принципиально. Вот вообщем-то и все. BB>>>>Можно пользовать в многопоточном приложении (для этого и задумывался), но есть сумнения. может вы, уважаемый алл, подскажите (выделенно жирным).
F>>>[покоцано]
BB>>>>Принимается любая критика по поводу кода.
F>>>Любую критику, говорите, принимаете? Итак:
F>>>1. Уберите от греха __fastcall. Тогда класс можно будет использовать в средах, отличных от Borland C++ Builder .
F>>>2. По коду (убрал все __fastcall, ну и так, замечания по ходу):
F>>>
F>>>// - header ---
F>>>class CBlackMutex
F>>>{
F>>> int Size;
F>>> long ResCount;
F>>> HANDLE hEvents[2];
F>>>public:
F>>> CBlackMutex(int sz=5); // лучше unsigned int
F>>> ~CBlackMutex();
F>>> bool Open();
F>>> bool Release();
F>>> HANDLE GetEmpty(){return hEvents[1];}
F>>> HANDLE GetOpened(){return hEvents[0];}
F>>>};
F>>>// - code ---
F>>>CBlackMutex::CBlackMutex(unsigned int sz) // добавил unsigned
F>>>{
F>>> // если unsigned, то проверку можно убрать
F>>>// if (sz <= 0) sz = 1;
F>>> Size = sz;
F>>> ResCount = 0;
F>>> hEvents[0] = hEvents[1] = NULL;
F>>> hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
F>>> hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
F>>>}
F>>>CBlackMutex::~CBlackMutex()
F>>>{
F>>>// Тут я немножко подрезал код... И так все ясно, без != NULL
F>>>// if (hEvents[0] != NULL) CloseHandle(hEvents[0]);
F>>>// if (hEvents[1] != NULL) CloseHandle(hEvents[1]);
F>>> if ( hEvents[0] ) CloseHandle(hEvents[0]);
F>>> if ( hEvents[1] ) CloseHandle(hEvents[1]);
F>>>// это зачем???
F>>>// hEvents[0] = hEvents[1] = NULL;
F>>>}
F>>>bool CBlackMutex::Open()
F>>>{
F>>> if (InterlockedExchangeAdd(&ResCount, 0) == Size) return false;
F>>> if (InterlockedExchangeAdd(&ResCount, 0) == 0)
F>>> {
F>>> SetEvent(hEvents[0]); // нет проверки ошибок...
F>>> }
F>>> InterlockedExchangeAdd(&ResCount, 1); // multithreading ++ :D
F>>> return true;
F>>>}
F>>>bool CBlackMutex::Release()
F>>>{
F>>> if (InterlockedExchangeAdd(&ResCount, 0) == 0) return false;
F>>> InterlockedExchangeAdd(&ResCount, -1); // multithreading -- :D
F>>> if (InterlockedExchangeAdd(&ResCount, 0) == 0)
F>>> {
F>>> SetEvent(hEvents[1]); // нет проверки ошибок...
F>>> }
F>>> return true;
F>>>}
F>>>
F>>>Вот, в общем... Сами просили
AS>>И я тут поучаствую AS>>
AS>>CBlackMutex::~CBlackMutex()
AS>>{
AS>>// Я бы сделал во как
AS>> if ( hEvents[0] != INVALID_HANDLE_VALUE) CloseHandle(hEvents[0]);
AS>> if ( hEvents[1] != INVALID_HANDLE_VALUE ) CloseHandle(hEvents[1]);
AS>> hEvents[0] = hEvents[1] = INVALID_HANDLE_VALUE;
AS>>}
AS>>
А>ну здесь ты не прав, т.к. в случае ошибки CreateEvent() возвращает NULL, а не INVALID_HANDLE_VALUE.
А>З.Ы. А>INVALID_HANDLE_VALUE = -1 А>NULL = 0
Здравствуйте Алекс, Вы писали:
А>Здравствуйте BlackBox, Вы писали:
BB>>Здравствуйте Алекс, Вы писали:
А>>>Здравствуйте BlackBox, Вы писали:
BB>>[skip]
А>>>я не буду оценивать нужность класса и его функционал, а только попридираюсь к коду. ок? А>>>1. нет конструктора по умолчанию — неудобно BB>>
BB>>CBlackMutex(int sz=5); // <--- не оно?
BB>>
А>сори, не заметил
BB>>чтобы получить значение не изменяя его.
А>не понял?
InterlockedExchangeAdd возвращает предыдущее значение. Следовательно InterlockedExchangeAdd(&ResCount, 0) вернет нам значение ResCount, не изменив его. Может оно конечно можно и просто так прочитать, но лучше уж так...
хъ
А>>не понял? BB>InterlockedExchangeAdd возвращает предыдущее значение. Следовательно InterlockedExchangeAdd(&ResCount, 0) вернет нам значение ResCount, не изменив его. Может оно конечно можно и просто так прочитать, но лучше уж так...
Здравствуйте Алекс, Вы писали:
А>Здравствуйте BlackBox, Вы писали:
А>хъ
А>>>не понял? BB>>InterlockedExchangeAdd возвращает предыдущее значение. Следовательно InterlockedExchangeAdd(&ResCount, 0) вернет нам значение ResCount, не изменив его. Может оно конечно можно и просто так прочитать, но лучше уж так...
А>Дык чем лучше-то?
InterlockedExchangeAdd получает монопольный доступ к изменяемой переменной. Пока она не вернет нам значение никто его изменить не сможет.
Пока тебе писал, мысль родилась может весь код работающий с внутреннми переменными в критическую секцию засунуть? Так действительно будет более монопольный доступ.
Здравствуйте BlackBox, Вы писали:
BB>Здравствуйте Алекс, Вы писали:
А>>Здравствуйте BlackBox, Вы писали:
А>>хъ
А>>>>не понял? BB>>>InterlockedExchangeAdd возвращает предыдущее значение. Следовательно InterlockedExchangeAdd(&ResCount, 0) вернет нам значение ResCount, не изменив его. Может оно конечно можно и просто так прочитать, но лучше уж так...
А>>Дык чем лучше-то?
BB>InterlockedExchangeAdd получает монопольный доступ к изменяемой переменной. Пока она не вернет нам значение никто его изменить не сможет.
Ты думаешь, что пока ты читаешь значение переменной в регистр кто-то ее изменит? Однако!
Здравствуйте Алекс, Вы писали:
А>Здравствуйте BlackBox, Вы писали:
BB>>Здравствуйте Алекс, Вы писали:
А>>>Здравствуйте BlackBox, Вы писали:
А>>>хъ
А>>>>>не понял? BB>>>>InterlockedExchangeAdd возвращает предыдущее значение. Следовательно InterlockedExchangeAdd(&ResCount, 0) вернет нам значение ResCount, не изменив его. Может оно конечно можно и просто так прочитать, но лучше уж так...
А>>>Дык чем лучше-то?
BB>>InterlockedExchangeAdd получает монопольный доступ к изменяемой переменной. Пока она не вернет нам значение никто его изменить не сможет.
А>Ты думаешь, что пока ты читаешь значение переменной в регистр кто-то ее изменит? Однако!
а ты её обьяви как volatile...компилятор её в регистры и не будет запихивать.
KA>Chto to eto ochen pohozhe na semafor, esli net, chto ne hvataet v semafore ?
Да название я немного неверное придумал. Это действительно больше похоже на семафор.
Различие в том, что мой объект переходит в свободное состояние дважды (когда полностью свободен и когда только что перешел из свободного состояния), тогда как семафор только, когда его кто-нибудь открывает (насколько я понимаю семафор).
Здравствуйте Хитрик Денис, Вы писали:
ХД>Товарищи, имейте совесть! ХД>Зачем ради одной фразы цитировать весть предыдущий ответ, который тоже не блещет предответной обработкой?
ХД>Получите ноль.
да просто забыл! извиняюсь.
Вообще лучше сделать так (если сервак совсем нагибается):
1. не показывать текст предыдущего сообщения при ответе
2. завести кнопочку, которая вставляет текст предыдущего сообщения
Это приведет к тому что:
1. будут вставлять цитаты только тогда, когда они действительно нужны
2. уменишит общий вес (в байтах) топика
3. все будут довольны