unused<T>
От: remark Россия http://www.1024cores.net/
Дата: 13.08.10 11:41
Оценка: 39 (3) -1
Из той же оперы, что и auto_value&lt;&gt;
Автор: Кодт
Дата: 16.01.03
.

Иногда приходится писать код типа:
DWORD err = GetLastError();
(void)err;

BOOL res = CloseHandle(f);
assert(res);
(void)res;


Дабы сократить 1 строчку, подумалось:
template<typename T>
class unused
{
public:
    unused(T v) : v(v) {}
    unused(unused const& v) : v(v.v) {}
    operator T () const {return v;}
private:
    void operator = (unused const&);
    T volatile const v;
};

unused<DWORD> err = GetLastError();

unused<BOOL> res = CloseHandle(fout);
assert(res);


З.ы. volatile важен, т.к. обычно его забываешь ставить, и потом в релизе до истины уже не докапаешься.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: unused<T>
От: Erop Россия  
Дата: 13.08.10 11:52
Оценка:
Здравствуйте, remark, Вы писали:

R>
R>    unused(unused const& v) : v(v.v) {}
R>private:
R>    void operator = (unused const&);
R>


Зачем это всё? Зачем свой конструктор копии и зачем запрет присваивания?
Или фишка в том, что нельзя поменять? Тогда, по идее, нужен не operator T, а operator const T&

R>З.ы. volatile важен, т.к. обычно его забываешь ставить, и потом в релизе до истины уже не докапаешься.

Ну и название мне не нравится, конечно. Фраза
unused<DWORD> res = GetLastError();
checkError( res );
нифига не читабельная. Может как-то типа debug_variable назвать, например?

R>

Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: unused<T>
От: Erop Россия  
Дата: 13.08.10 11:53
Оценка:
Здравствуйте, remark, Вы писали:


R>Дабы сократить 1 строчку, подумалось:


А вообще, конечно, цель сократить одну строчку ложная.
Другое дело, что волотайл может быть в тему.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: unused<T>
От: night beast СССР  
Дата: 13.08.10 11:57
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, remark, Вы писали:


R>>
R>>    unused(unused const& v) : v(v.v) {}
R>>private:
R>>    void operator = (unused const&);
R>>


E>Зачем это всё? Зачем свой конструктор копии и зачем запрет присваивания?

E>Или фишка в том, что нельзя поменять? Тогда, по идее, нужен не operator T, а operator const T&

думаю, чтобы подавить варнинг неиспользуемой переменной в релизе.
Re[3]: unused<T>
От: Erop Россия  
Дата: 13.08.10 12:05
Оценка:
Здравствуйте, night beast, Вы писали:

NB>думаю, чтобы подавить варнинг неиспользуемой переменной в релизе.

Как-то это ненадёжно.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: unused<T>
От: night beast СССР  
Дата: 13.08.10 12:06
Оценка:
Здравствуйте, Erop, Вы писали:

NB>>думаю, чтобы подавить варнинг неиспользуемой переменной в релизе.

E>Как-то это ненадёжно.

почему?
Re: unused<T>
От: uzhas Ниоткуда  
Дата: 13.08.10 12:13
Оценка:
Здравствуйте, remark, Вы писали:

Аналогичные вопросы обсуждались здесь
http://rsdn.ru/forum/cpp/3655065.flat.aspx
Автор: remark
Дата: 28.12.09

http://rsdn.ru/forum/cpp/3787064.flat.aspx
Автор: uzhas
Дата: 26.04.10


R>unused<BOOL> res = CloseHandle(fout);

R>assert(res);
а так сможете?
unused<std::string> res = FetchName(db);
assert(!res.empty());
Re: unused<T>
От: Кодт Россия  
Дата: 13.08.10 12:14
Оценка:
Здравствуйте, remark, Вы писали:

Всё-таки, unused — это write-only. Ассерт — это уже не совсем unused
Можно так
template<class T>
class unused : noncopyable
{
#ifdef _DEBUG

  T data;
public:
  unused(const T& v) : data(v) {}
  operator const T& () const { return data; }

#else

public:
  unused(const T& v) {}
  operator const T& () const { PANIC(); }

#endif
};


В чём прикол с volatile, не понял. И почему нельзя по месту писать unused<volatile T>, если известно, что функция возвращает volatile?
Перекуём баги на фичи!
Re[2]: unused<T>
От: remark Россия http://www.1024cores.net/
Дата: 13.08.10 12:18
Оценка:
Здравствуйте, Erop, Вы писали:

E>А вообще, конечно, цель сократить одну строчку ложная.


А что делать, если надо обернуть кучу WinAPI/POSIX, и таких мест дофига?
В паре месте написать лишнюю строчку нормально, но в десятках тоже как-то не очень имвхо...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: unused<T>
От: remark Россия http://www.1024cores.net/
Дата: 13.08.10 12:20
Оценка: +1
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, remark, Вы писали:


U>Аналогичные вопросы обсуждались здесь

U>http://rsdn.ru/forum/cpp/3655065.flat.aspx
Автор: remark
Дата: 28.12.09

U>http://rsdn.ru/forum/cpp/3787064.flat.aspx
Автор: uzhas
Дата: 26.04.10



Для параметров это немного другое получается.
Тут идея как бы совместить переменную и unused.


R>>unused<BOOL> res = CloseHandle(fout);

R>>assert(res);
U>а так сможете?
U>
U>unused<std::string> res = FetchName(db);
U>assert(!res.empty());
U>


Ну... можно перегрузить operator->(), тогда будет:
assert(!res->empty());



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: unused<T>
От: superlexx  
Дата: 13.08.10 12:21
Оценка: +1
Здравствуйте, remark, Вы писали:

R>template<typename T> class unused


Проще надо быть:
VERIFY(CloseHandle(x));
Если на результаты хочется посмотреть, то найдёте их в регистрах. GetLastError -- $err,hr в Watch
verify
Re[2]: unused<T>
От: remark Россия http://www.1024cores.net/
Дата: 13.08.10 12:24
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Всё-таки, unused — это write-only. Ассерт — это уже не совсем unused

К>Можно так
К>
К>template<class T>
К>class unused : noncopyable
К>{
К>#ifdef _DEBUG
К>  T data;
К>public:
К>  unused(const T& v) : data(v) {}
К>  operator const T& () const { return data; }
К>#else
К>public:
К>  unused(const T& v) {}
К>  operator const T& () const { PANIC(); }
К>#endif
К>};
К>


В релизе переменная тоже нужна, что бы видеть в отладчике или в дампе.


К>В чём прикол с volatile, не понял. И почему нельзя по месту писать unused<volatile T>, если известно, что функция возвращает volatile?


Если переменная используется только в assert'е, или вообще не используется (просто хочется видеть значение в отладчике/дампе), то в релизе её либо вообще не будет, либо она будет замешана где-то в регистрах.
Если же объявлять как:
DWORD volatile err = GetLastError();


То она в релизе не только останется, но даже и отладчик скорее всего будет показывать корректное значение.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: unused<T>
От: remark Россия http://www.1024cores.net/
Дата: 13.08.10 12:29
Оценка:
Здравствуйте, superlexx, Вы писали:

R>>template<typename T> class unused


S>Проще надо быть:
VERIFY(CloseHandle(x));
Если на результаты хочется посмотреть, то найдёте их в регистрах. GetLastError -- $err,hr в Watch


Это не то.
VERIFY не везде есть.
VERIFY выдаёт мессаджбокс.
В регистрах искать не очень круто при прочих равных.
В регистре значение будет очень не долго, а в дампе его вообще не будет.
Иногда со значением вообще ничего не надо делать, просто что бы было. $err надо успеть сделать, и вообще его надо делать.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: unused<T>
От: Кодт Россия  
Дата: 13.08.10 18:42
Оценка: 11 (1)
Здравствуйте, remark, Вы писали:

R>Это не то.

R>VERIFY не везде есть.
#define REMARK_VERIFY

R>VERIFY выдаёт мессаджбокс.

#define REMARK_VERIFY

R>В регистрах искать не очень круто при прочих равных.

R>В регистре значение будет очень не долго, а в дампе его вообще не будет.
#define REMARK_VERIFY(x) LBRACE auto tmp = x; assert(x); RBRACE

#define LBRACE do {
#define RBRACE } while(false)


R>Иногда со значением вообще ничего не надо делать, просто что бы было. $err надо успеть сделать, и вообще его надо делать.


Для пущей навороченности:
struct errors
{
  UINT m_lasterror;
  error_t m_errno, m_doserrno;

  errors() : m_lasterror(GetLastError()), m_errno(::errno), m_doserrno(::_doserrno) {}

  operator bool() const { return m_lasterror||m_errno||m_doserrno; }
};

template<class Value, class Assertion = Pofigu>
struct unused
{
  Value m_value;
  errors m_errors;

  unused(Value v) : m_value(v) { Assertion::assert(v, m_errors); }
};

struct Pofigu         { template<class Value> static void assert(Value v,   errors const& e) {               } };
struct AssertNoErrors { template<class Value> static void assert(Value v,   errors const& e) { ::assert(!e); } };
struct AssertNonZero  { template<class Value> static void assert(Value v,   errors const& e) { ::assert(v);  } };
struct AssertZero     { template<class Value> static void assert(Value v,   errors const& e) { ::assert(!v); } };
struct AssertHResult  {                       static void assert(HRESULT v, errors const& e) { ::assert(SUCCEEDED(hr)); } };
Перекуём баги на фичи!
Re: unused<T>
От: Vamp Россия  
Дата: 13.08.10 19:22
Оценка:
R>Иногда приходится писать код типа:
Я уже всю голову сломал, но так и не понял, зачем такой код приходится писать?

DWORD err = GetLastError();
(void)err;

Чтоза поведение обеспечивается?
Да здравствует мыло душистое и веревка пушистая.
Re[2]: unused<T>
От: Вертер  
Дата: 13.08.10 21:09
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Иногда приходится писать код типа:

V>Я уже всю голову сломал, но так и не понял, зачем такой код приходится писать?

V>Чтоза поведение обеспечивается?


чтобы Visual Studio не выдавал warning когда включен Level 4. Предупреждение будет, типа: «локальная переменная объявлена но не используется»
Re[3]: unused<T>
От: Vamp Россия  
Дата: 13.08.10 21:12
Оценка:
В>чтобы Visual Studio не выдавал warning когда включен Level 4. Предупреждение будет, типа: «локальная переменная объявлена но не используется»
А, спасибо, понял. Я бы правда скорее подавил предупреждение.
Да здравствует мыло душистое и веревка пушистая.
Re[4]: unused<T>
От: Вертер  
Дата: 13.08.10 21:22
Оценка:
В>>чтобы Visual Studio не выдавал warning когда включен Level 4. Предупреждение будет, типа: «локальная переменная объявлена но не используется»
V>А, спасибо, понял. Я бы правда скорее подавил предупреждение.

лучше этого не делать с помощью всяких подавителей иногда можно так и (логическую) ошибку пропустить.
Re[3]: unused<T>
От: minorlogic Украина  
Дата: 15.08.10 06:50
Оценка:
Здравствуйте, remark, Вы писали:

R>А что делать, если надо обернуть кучу WinAPI/POSIX, и таких мест дофига?


Первое что приходит в голову, враперы ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re: unused<T>
От: SleepyDrago Украина  
Дата: 15.08.10 15:52
Оценка: 1 (1)
Здравствуйте, remark, Вы писали:

R>З.ы. volatile важен, т.к. обычно его забываешь ставить, и потом в релизе до истины уже не докапаешься.


Идея сохранить удобства дебага в релизе с помощью volatile прикольная — все равно syscall штука недешевая так что запись в переменную считай бесплатно.

Идея не обрабатывать ошибки в релизе достойна порки.
Я не настаиваю на месадж боксах тк пишу и под линупс без гуя но альтернативы всегда есть — логи и тп. Даже если не собираетесь падать эта инфо может быть очень важна.
Re: unused<T>
От: SpaceConscience  
Дата: 15.08.10 16:14
Оценка:
А можно пример кода, желательно побольше, где такое используется?
Собрался ставить минус? Да сам иди в жопу!

































































.
Re: unused<T>
От: alexeiz  
Дата: 16.08.10 04:03
Оценка:
Здравствуйте, remark, Вы писали:

R>Из той же оперы, что и auto_value&lt;&gt;
Автор: Кодт
Дата: 16.01.03
.


R>Иногда приходится писать код типа:

R>
R>DWORD err = GetLastError();
R>(void)err;

R>BOOL res = CloseHandle(f);
R>assert(res);
R>(void)res;
R>


R>Дабы сократить 1 строчку, подумалось:

...

R>А что делать, если надо обернуть кучу WinAPI/POSIX, и таких мест дофига?


Я использую несколько другой вариант, который сродни перловскому оператору die. У меня он бросает исключение, но в принципе может делать всё что угодно (включая запись в volatile, что, по-моему, абсолютно лишнее). Внизу только простой юнит тест. Реализация оставляется как упражнение читателю .
#include "error_handler.hpp"

#include <exception>
#include <iostream>
#include <string>

#include <windows.h>

using namespace std;
using namespace err;

HRESULT test_ok()
{
    return S_OK;
}

HRESULT test_false()
{
    return S_FALSE;
}

HRESULT test_error()
{
    return E_INVALIDARG;
}

BOOL test_win32_success()
{
    return TRUE;
}

BOOL test_win32_error()
{
    SetLastError(HRESULT_CODE(E_FAIL));
    return FALSE;
}

int main()
try
{
    test_ok() || die;

    HRESULT hr = test_false() || die;
    if (hr != S_FALSE)
        throw runtime_error("wrong HRESULT");

    try
    {
        test_error() || die;
        throw runtime_error("didn't die");
    }
    catch (hresult_error & e)
    {
        if (e.hresult() != E_INVALIDARG)
            throw runtime_error("wrong HRESULT");
    }

    test_ok() || die("should be OK");
    test_ok() || die("should be OK with 1 parameter %1%")(1);
    test_ok() || die("should be OK with 10 parameters %1% %2% %3% %4% %5% %6% %7% %8% %9% %10%")(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

    try
    {
        test_error() || die("should throw");
        throw runtime_error("didn't die");
    }
    catch (hresult_error & e)
    {
        if (string(e.what()) != string("should throw"))
            throw runtime_error("wrong exception message");
    }

    try
    {
        test_error() || die("should throw with 10 parameters %1% %2% %3% %4% %5% %6% %7% %8% %9% %10%")(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        throw runtime_error("didn't die");
    }
    catch (hresult_error & e)
    {
        if (string(e.what()) != string("should throw with 10 parameters 1 2 3 4 5 6 7 8 9 10"))
            throw runtime_error("wrong exception message");
    }

    try
    {
        test_error() || die("should throw with 1 parameter %1%")(1);
        throw runtime_error("didn't die");
    }
    catch (hresult_error & e)
    {
        if (string(e.what()) != string("should throw with 1 parameter 1"))
            throw runtime_error("wrong exception message");
    }

    test_win32_success() || die;

    try
    {
        test_win32_error() || die;
        throw runtime_error("didn't die");
    }
    catch (win32_error & e)
    {
        if (e.error_code() != HRESULT_CODE(E_FAIL))
            throw runtime_error("wrong error code");
    }

    test_win32_success() || die("should be OK");

    try
    {
        HANDLE file = CreateFile(L"c:\\some_dir\\some_other_dir\\some_file", 0, 0, 0, 0, 0, 0)
            || die("can't create file");
        throw runtime_error("didn't die");
    }
    catch (win32_error &)
    {}

    if (hresult_error::format_message(E_FAIL) != string("Unspecified error\r\n"))
        throw runtime_error("wrong HRESULT message");

    if (win32_error::format_message(ERROR_ACCESS_DENIED) != string("Access is denied.\r\n"))
        throw runtime_error("wrong GetLastError message");

    cout << "SUCCEEDED\n";
}
catch (exception & e)
{
    cerr << "FAILED: " << e.what() << endl;
    return -1;
}
Re: unused<T>
От: rm822 Россия  
Дата: 16.08.10 08:41
Оценка: +1
Хороший пример того как неправильные практики приводят к дуратским решениям
Ошибки обрабатывать нужно ВСЕГДА, а не только в дебаге
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: unused<T>
От: Тот кто сидит в пруду Россия  
Дата: 16.08.10 10:45
Оценка:
Здравствуйте, Vamp, Вы писали:

В>>чтобы Visual Studio не выдавал warning когда включен Level 4. Предупреждение будет, типа: «локальная переменная объявлена но не используется»

V>А, спасибо, понял. Я бы правда скорее подавил предупреждение.

Да не, там немного другое — обеспечивается еще и невыкидывание этой переменной оптимизатором. Насколько я понял, чтобы в релизе можно было посмотреть ее значение. Лично я, впрочем, обычно предпочитаю логгирование, ну да случаи всякие бывают.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 08:52
Оценка: +1
Отвечу сразу всем тут.
Во-первых, я не навязываю использование это штуки. Просто приём, сами смотрите нужно не нужно.
Во-вторых, не всегда можно логировать и даже не всегда можно вернуть ошибку. Вы смотрите со стороны кода конечного приложения, а если это, например, библиотека. Например, библиотека реализующая многопоточность из C1x. Логирование — это определенно не то, чего хочет пользователь от такой библиотека. Ошибки из некоторых функций вообще не вернуть (такая сигнатура), или не все можно отмапить (там очень маленький фиксированный список). И что делать в такой ситуации?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: По поводу применимости
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.10 12:34
Оценка:
Здравствуйте, remark, Вы писали:

R>Отвечу сразу всем тут.

R>Во-первых, я не навязываю использование это штуки. Просто приём, сами смотрите нужно не нужно.
R>Во-вторых, не всегда можно логировать и даже не всегда можно вернуть ошибку. Вы смотрите со стороны кода конечного приложения, а если это, например, библиотека. Например, библиотека реализующая многопоточность из C1x. Логирование — это определенно не то, чего хочет пользователь от такой библиотека. Ошибки из некоторых функций вообще не вернуть (такая сигнатура), или не все можно отмапить (там очень маленький фиксированный список). И что делать в такой ситуации?

Логировать точно не надо.
Очевидно что пользователи ограничены только спецификацией библиотеки, поэтому логично предположить что при желании пользователя изменить реализацию на другую поведение самой программы не должно измениться (при условии что реализация корректна). Можно, например начать кидать исключение (выставлять errno, и т.д.) и явно задокументировать это, но в этом случае пользователь станет привязанным к конкретной реализации (т.к. он потенциально готов к этому исключению и возможно будет его обрабатывать). Изменение контракта в этом случае — это прямое нарушение LSP с соответствующими последствиями. Выхода здесь два — не использовать механизмы которые могут привести к озвученной ситуации, либо все-таки свернуть возможные ошибки в более узкий класс, как того требует спецификация.
Re[3]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 12:59
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Логировать точно не надо.

ЮЖ>Очевидно что пользователи ограничены только спецификацией библиотеки, поэтому логично предположить что при желании пользователя изменить реализацию на другую поведение самой программы не должно измениться (при условии что реализация корректна). Можно, например начать кидать исключение (выставлять errno, и т.д.) и явно задокументировать это, но в этом случае пользователь станет привязанным к конкретной реализации (т.к. он потенциально готов к этому исключению и возможно будет его обрабатывать). Изменение контракта в этом случае — это прямое нарушение LSP с соответствующими последствиями. Выхода здесь два — не использовать механизмы которые могут привести к озвученной ситуации, либо все-таки свернуть возможные ошибки в более узкий класс, как того требует спецификация.

Это один выход — не использовать механизмы которые могут привести к озвученной ситуации *И* свернуть возможные ошибки в более узкий класс, как того требует спецификация.

Тут теряется информация (иногда сводить придётся к void). Так чем же хуже ещё к этому и дать отлаживающему пользователю информацию в удобной форме?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: По поводу применимости
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.10 13:41
Оценка:
Здравствуйте, remark, Вы писали:

R>Это один выход — не использовать механизмы которые могут привести к озвученной ситуации *И* свернуть возможные ошибки в более узкий класс, как того требует спецификация.


Почему *И*? Например, в том же winapi все коды ошибок можно свернуть к {успех, неудача}... Механизм используется, ошибки свернуты.

Хотя здесь еще один аспект есть, но он относится по большему счету к полноте спецификации — описание возможных побочных эффектов ("чистота" функций, сложность выполнения и т.п). Это может налагать дополнительные ограничения на реализацию.

R>Тут теряется информация (иногда сводить придётся к void). Так чем же хуже ещё к этому и дать отлаживающему пользователю информацию в удобной форме?


Ведет ли себя (библиотечная) функция в этом случае корректно (в рамках контракта)?
Re[5]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 13:45
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Здравствуйте, remark, Вы писали:


R>>Это один выход — не использовать механизмы которые могут привести к озвученной ситуации *И* свернуть возможные ошибки в более узкий класс, как того требует спецификация.


ЮЖ>Почему *И*? Например, в том же winapi все коды ошибок можно свернуть к {успех, неудача}... Механизм используется, ошибки свернуты.


Потому что они при этом не нарушают свой контракт.


R>>Тут теряется информация (иногда сводить придётся к void). Так чем же хуже ещё к этому и дать отлаживающему пользователю информацию в удобной форме?


ЮЖ>Ведет ли себя (библиотечная) функция в этом случае корректно (в рамках контракта)?


Я не вижу каким образом в контракте может быть специфицировано, что функция не должна создавать на стеке каких-то определенных переменных.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: По поводу применимости
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.10 14:07
Оценка:
Здравствуйте, remark, Вы писали:

R>>>Это один выход — не использовать механизмы которые могут привести к озвученной ситуации *И* свернуть возможные ошибки в более узкий класс, как того требует спецификация.


ЮЖ>>Почему *И*? Например, в том же winapi все коды ошибок можно свернуть к {успех, неудача}... Механизм используется, ошибки свернуты.


R>Потому что они при этом не нарушают свой контракт.


? "не использовать механизмы ... *И* свернуть ..." != "Механизм используется, ошибки свернуты"

R>>>Тут теряется информация (иногда сводить придётся к void). Так чем же хуже ещё к этому и дать отлаживающему пользователю информацию в удобной форме?


ЮЖ>>Ведет ли себя (библиотечная) функция в этом случае корректно (в рамках контракта)?


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


Я имею ввиду игнорирование вызовов CloseHandle/GetLastError/. Или ты говоришь о таких случаях:

error_code foo()
{
    if(!api::bar())
    {
        DWORD err = GetLastError();
        (void)err;
        return error_x;
    }
...
Re[7]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 14:16
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Здравствуйте, remark, Вы писали:


R>>>>Это один выход — не использовать механизмы которые могут привести к озвученной ситуации *И* свернуть возможные ошибки в более узкий класс, как того требует спецификация.


ЮЖ>>>Почему *И*? Например, в том же winapi все коды ошибок можно свернуть к {успех, неудача}... Механизм используется, ошибки свернуты.


R>>Потому что они при этом не нарушают свой контракт.


ЮЖ>? "не использовать механизмы ... *И* свернуть ..." != "Механизм используется, ошибки свернуты"


В WinAPI НЕ используются механизмы, которые приводят к нарешению контракта *И* ошибки свёрнуты.



R>>>>Тут теряется информация (иногда сводить придётся к void). Так чем же хуже ещё к этому и дать отлаживающему пользователю информацию в удобной форме?


ЮЖ>>>Ведет ли себя (библиотечная) функция в этом случае корректно (в рамках контракта)?


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


ЮЖ>Я имею ввиду игнорирование вызовов CloseHandle/GetLastError/. Или ты говоришь о таких случаях:


ЮЖ>
ЮЖ>error_code foo()
ЮЖ>{
ЮЖ>    if(!api::bar())
ЮЖ>    {
ЮЖ>        DWORD err = GetLastError();
ЮЖ>        (void)err;
ЮЖ>        return error_x;
ЮЖ>    }
ЮЖ>...
ЮЖ>


Что-то типа такого... только надо ещё volatile добавить, иначе в релизе не будет работать.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: По поводу применимости
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.10 14:54
Оценка:
Здравствуйте, remark, Вы писали:

R>>>>>Это один выход — не использовать механизмы которые могут привести к озвученной ситуации *И* свернуть возможные ошибки в более узкий класс, как того требует спецификация.


ЮЖ>>>>Почему *И*? Например, в том же winapi все коды ошибок можно свернуть к {успех, неудача}... Механизм используется, ошибки свернуты.


R>>>Потому что они при этом не нарушают свой контракт.


ЮЖ>>? "не использовать механизмы ... *И* свернуть ..." != "Механизм используется, ошибки свернуты"


R>В WinAPI НЕ используются механизмы, которые приводят к нарешению контракта *И* ошибки свёрнуты.


Не понимаю о чем ты... "Механизм используется, ошибки свернуты" — это один из способов реализации, которая удовлетворяет контракту.

ЮЖ>>Я имею ввиду игнорирование вызовов CloseHandle/GetLastError/. Или ты говоришь о таких случаях:


ЮЖ>>
ЮЖ>>error_code foo()
ЮЖ>>{
ЮЖ>>    if(!api::bar())
ЮЖ>>    {
ЮЖ>>        DWORD err = GetLastError();
ЮЖ>>        (void)err;
ЮЖ>>        return error_x;
ЮЖ>>    }
ЮЖ>>...
ЮЖ>>


R>Что-то типа такого... только надо ещё volatile добавить, иначе в релизе не будет работать.


В таком варианте — не вижу особого смысла, если же способ передачи подробной информации об ошибках в нижних слоях наверх действительно нужен — то тут нужно думать... Хотя сокрытие деталей — одна из причин введения дополнительных уровней абстракции.
Re[9]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 14:59
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>>>>>Почему *И*? Например, в том же winapi все коды ошибок можно свернуть к {успех, неудача}... Механизм используется, ошибки свернуты.


R>>>>Потому что они при этом не нарушают свой контракт.


ЮЖ>>>? "не использовать механизмы ... *И* свернуть ..." != "Механизм используется, ошибки свернуты"


R>>В WinAPI НЕ используются механизмы, которые приводят к нарешению контракта *И* ошибки свёрнуты.


ЮЖ>Не понимаю о чем ты... "Механизм используется, ошибки свернуты" — это один из способов реализации, которая удовлетворяет контракту.


А я на понимаю о чём. Ты написал "либо не использовать механизмы, которые приводят к нарушение контрактов". В WinAPI такие механихмы не используются. Теперь ты пишешь, что какой-то механизм используется. Какой? Где?



ЮЖ>>>Я имею ввиду игнорирование вызовов CloseHandle/GetLastError/. Или ты говоришь о таких случаях:


ЮЖ>>>
ЮЖ>>>error_code foo()
ЮЖ>>>{
ЮЖ>>>    if(!api::bar())
ЮЖ>>>    {
ЮЖ>>>        DWORD err = GetLastError();
ЮЖ>>>        (void)err;
ЮЖ>>>        return error_x;
ЮЖ>>>    }
ЮЖ>>>...
ЮЖ>>>


R>>Что-то типа такого... только надо ещё volatile добавить, иначе в релизе не будет работать.


ЮЖ>В таком варианте — не вижу особого смысла, если же способ передачи подробной информации об ошибках в нижних слоях наверх действительно нужен — то тут нужно думать... Хотя сокрытие деталей — одна из причин введения дополнительных уровней абстракции.


Это — пожалуйста, я никого не принуждаю.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: По поводу применимости
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.10 15:27
Оценка:
Здравствуйте, remark, Вы писали:

ЮЖ>>в том же winapi все коды ошибок можно свернуть к {успех, неудача}


ЮЖ>>Не понимаю о чем ты... "Механизм используется, ошибки свернуты" — это один из способов реализации, которая удовлетворяет контракту.


R>А я на понимаю о чём. Ты написал "либо не использовать механизмы, которые приводят к нарушение контрактов". В WinAPI такие механихмы не используются.


Я этого не говорил.

"В ... winapi все коды ошибок можно свернуть к {успех, неудача}":

bool init()
{
    return SUCCEEDED(CoInitialize(NULL));
}


R>Теперь ты пишешь, что какой-то механизм используется. Какой?


Который необходим.

R>Где?


В реализации.

Примерно так (если не вдаваться в смысл функций):

/// \return NULL при ошибке
/// \throw none
int* get();


// реализация 1
int* get()
{
  // механизм (выделения памяти) используется, ошибки не свернуты  => нарушение контракта
  return new int;
}

// реализация 2
int* get()
{
  // механизм (выделения памяти) используется, ошибки свернуты  => один из выходов
  return new(std::nothrow) int;
}

// реализация 3
int* get()
{
  // Отказались от механизма => один из выходов
  return g_int_ptr;
}
Re[11]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 15:36
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>>>в том же winapi все коды ошибок можно свернуть к {успех, неудача}


ЮЖ>>>Не понимаю о чем ты... "Механизм используется, ошибки свернуты" — это один из способов реализации, которая удовлетворяет контракту.


R>>А я на понимаю о чём. Ты написал "либо не использовать механизмы, которые приводят к нарушение контрактов". В WinAPI такие механихмы не используются.


ЮЖ>Я этого не говорил.


Я это говорю. А что там используются какие-то механизмы, которые нарушают контракты?
Вариант-то один — И не использовать механизмы, которые нарушают контракт, *И* сводить все ошибки к тому, что дано в контракте. И это неминуемо ведёт к потере информации.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 15:38
Оценка:
R>Вариант-то один — И не использовать механизмы, которые нарушают контракт, *И* сводить все ошибки к тому, что дано в контракте. И это неминуемо ведёт к потере информации.
Ну отчего же. Можно использовать механизмы вроде errno — GetLastError.
Да здравствует мыло душистое и веревка пушистая.
Re[13]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 15:47
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Вариант-то один — И не использовать механизмы, которые нарушают контракт, *И* сводить все ошибки к тому, что дано в контракте. И это неминуемо ведёт к потере информации.


V>Ну отчего же. Можно использовать механизмы вроде errno — GetLastError.


Это — тоже контакт. Если это не прописано в контракте, то нельзя. Ну или точнее — бессмысленно. То же самое, что я и предлагаю, только не удобно.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[14]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 15:49
Оценка:
R>Это — тоже контакт. Если это не прописано в контракте, то нельзя. Ну или точнее — бессмысленно.

Отчего же бессмысленно? Можно расширить функциональность, не нарушая контракта.
Да здравствует мыло душистое и веревка пушистая.
Re[12]: По поводу применимости
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.10 15:50
Оценка:
Здравствуйте, remark, Вы писали:

R>Вариант-то один — И не использовать механизмы, которые нарушают контракт, *И* сводить все ошибки к тому, что дано в контракте.


См. две первые реализации 'get' из предыдущего ответа. "Механизм" используется в двух реализациях, но тем не менее в одной есть нарушение контракта (именно по причине использования этого механизма), а в другой нет.
Re[15]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 15:57
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Это — тоже контакт. Если это не прописано в контракте, то нельзя. Ну или точнее — бессмысленно.


V>Отчего же бессмысленно? Можно расширить функциональность, не нарушая контракта.


От того, что пользователи используют функциональность через контракт. Если в контракте этого нет, то это бессмысленно. Пользователь не знает ни о чём, кроме контракта.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[13]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 15:59
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Здравствуйте, remark, Вы писали:


R>>Вариант-то один — И не использовать механизмы, которые нарушают контракт, *И* сводить все ошибки к тому, что дано в контракте.


ЮЖ>См. две первые реализации 'get' из предыдущего ответа. "Механизм" используется в двух реализациях, но тем не менее в одной есть нарушение контракта (именно по причине использования этого механизма), а в другой нет.


И как оттуда вернуть ошибку "нет прав для выделения памяти" именно через такой контакт "возвращается указатель на int или 0"?
Никак. Там просто тупо давятся все ошибки.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[16]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 16:05
Оценка:
R>От того, что пользователи используют функциональность через контракт. Если в контракте этого нет, то это бессмысленно. Пользователь не знает ни о чём, кроме контракта.
Ну от чего же? Допустим, у нас выходит новая версия библиотеки, которая поддерживает расширенную информацию об ошибках. Контракт нарушать нельзя в целях обратной совместимости. Введя дополнительную функцию можно обеспечить расширение функциональности без нарушения контракта.
Да здравствует мыло душистое и веревка пушистая.
Re[14]: По поводу применимости
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.10 16:10
Оценка:
Здравствуйте, remark, Вы писали:

ЮЖ>>См. две первые реализации 'get' из предыдущего ответа. "Механизм" используется в двух реализациях, но тем не менее в одной есть нарушение контракта (именно по причине использования этого механизма), а в другой нет.


R>И как оттуда вернуть ошибку "нет прав для выделения памяти" именно через такой контакт "возвращается указатель на int или 0"?

R>Никак. Там просто тупо давятся все ошибки.

Давятся, т.к. на уровне контракта в общем случае невозможно специфицировать все возможные ошибки, которые могут возникнуть в реализации.
Re[17]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 16:14
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>От того, что пользователи используют функциональность через контракт. Если в контракте этого нет, то это бессмысленно. Пользователь не знает ни о чём, кроме контракта.


V>Ну от чего же? Допустим, у нас выходит новая версия библиотеки, которая поддерживает расширенную информацию об ошибках. Контракт нарушать нельзя в целях обратной совместимости. Введя дополнительную функцию можно обеспечить расширение функциональности без нарушения контракта.


Ты говоришь о ситуации, когда можно менять контракт. Тут действительно нет проблеим.
Я говорю о ситуации, когда контракт менять нельзя. Нужно решить в рамках данного контракта. И тут решений нет. Поэтому я и довольствуюсь тем, что разработчика при отладке кинет на нужный ассёрт, и у него будет вся необходимая информация под рукой. Всё лучше, чем без этого.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[15]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 16:17
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>>>См. две первые реализации 'get' из предыдущего ответа. "Механизм" используется в двух реализациях, но тем не менее в одной есть нарушение контракта (именно по причине использования этого механизма), а в другой нет.


R>>И как оттуда вернуть ошибку "нет прав для выделения памяти" именно через такой контакт "возвращается указатель на int или 0"?

R>>Никак. Там просто тупо давятся все ошибки.

ЮЖ>Давятся, т.к. на уровне контракта в общем случае невозможно специфицировать все возможные ошибки, которые могут возникнуть в реализации.


Вот это я и пытаюсь решить.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[18]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 16:28
Оценка:
R>Ты говоришь о ситуации, когда можно менять контракт. Тут действительно нет проблеим.
R>Я говорю о ситуации, когда контракт менять нельзя.

Как правило, с практической точки зрения введение дополнительных функций не является нарушением контракта, так как не нарушает работу ранее существовавших приложений. Изменение же возвращаемого значения, безусловно, является.
Да здравствует мыло душистое и веревка пушистая.
Re[19]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 16:30
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Ты говоришь о ситуации, когда можно менять контракт. Тут действительно нет проблеим.

R>>Я говорю о ситуации, когда контракт менять нельзя.

V>Как правило, с практической точки зрения введение дополнительных функций не является нарушением контракта, так как не нарушает работу ранее существовавших приложений. Изменение же возвращаемого значения, безусловно, является.


Введение дополнительных функций конечно не является нарушением контракта, но и бессмысленно.
Интересно у кого раньше стек кончится...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[20]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 16:38
Оценка:
R>Введение дополнительных функций конечно не является нарушением контракта, но и бессмысленно.
R>Интересно у кого раньше стек кончится...
Такое ощущение, что ты меня не слышишь. Попробую объяснить на очень простом примере.
У тебя есть библиотека, вызывающая некоторое системное API. На момент разработки библиотеки API возврашало bool — success or failure. Соответствено, библиотечная функция тоже возвращала bool — предположим, собственных ошибок она породить не могла. В новой версии ОС API стало предоставлять дополнительные сведения об ошибках, и ты хочешь вернуть их пользователю.
Расширять возвращаемое значение нельзя — посыпятся старые приложения. Единственный выход — ввести дополнительную функцию возврата расширеной ошибки. Таким образом обеспечивается обратная совместимость и предоставляются механизмы для тех, кто может ими воспользоваться.
Да здравствует мыло душистое и веревка пушистая.
Re[21]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 16:47
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Введение дополнительных функций конечно не является нарушением контракта, но и бессмысленно.

R>>Интересно у кого раньше стек кончится...

V>Такое ощущение, что ты меня не слышишь. Попробую объяснить на очень простом примере.

V>У тебя есть библиотека, вызывающая некоторое системное API. На момент разработки библиотеки API возврашало bool — success or failure. Соответствено, библиотечная функция тоже возвращала bool — предположим, собственных ошибок она породить не могла. В новой версии ОС API стало предоставлять дополнительные сведения об ошибках, и ты хочешь вернуть их пользователю.
V>Расширять возвращаемое значение нельзя — посыпятся старые приложения. Единственный выход — ввести дополнительную функцию возврата расширеной ошибки. Таким образом обеспечивается обратная совместимость и предоставляются механизмы для тех, кто может ими воспользоваться.


Я тебя слышу, только ты говоришь о совершенно другой ситуации, когда мы можем менять контракт — твоя новая функция возврата расширенной ошибки — это новый контракт. В такой ситуации всё достаточно прозрачно и просто.

Я говорю о ситуации, когда контракт менять нельзя.
Допустим у меня есть моя реализация библиотеки pthreads, с расширенными функциями. Ты сейчас в своём приложении их используешь? Нет. Потому что тебе фиолетово на мой *новый* контракт, ты пишешь под POSIX. ДОпустим я тебе даю свою библиотеку. Тебе есть какая-то польза от этих расширенных функций? Нет. Потому что во-первы[, у тебя куча кода именно под POSIX, а во-вторых ты просто не хочешь затачивать свою программу под мой контракт, т.к. после этого под POSIX она даже компилироваться не будет.
Ну и что, имеет мне смысл менять контракт POSIX? Вот как хочешь, так под интерфейсом POSIX и пляши, даже если pthread_create() вызывает CreateThread(), которая может возвращать INVALID_SECURITY_DESCRIPTOR.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[22]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 16:53
Оценка:
R>Допустим у меня есть моя реализация библиотеки pthreads, с расширенными функциями.

Ты пишешь не о контрактах, а о стандартах. Если твоя библиотека реализует некий СТАНДАРТ — то да, не убавить, ни прибавить. Но далеко не все контракты привязаны к стандартам. Кстати, даже в твоем примере, я не согласен.
ПОСИКС ориентирован на Nix. Если ты реализуешь кросслпатформенный посикс, умеющий работать в том числе под вин, то да, вполне можно ввести туда дополнительные функции типа get_win_error. В этом случае те, кому нужна чистая кроссплатформенность не будут ее использовать (а могут и использовать, если функция будет уметь закорачивать себя в иных средах), а те, кого интересует только виндовая имплементация — получат преимущества дополнительной диагностики.
Так что даже в твоем примере вполне полезно.
Да здравствует мыло душистое и веревка пушистая.
Re[16]: По поводу применимости
От: Юрий Жмеренецкий ICQ 380412032
Дата: 18.08.10 16:58
Оценка:
Здравствуйте, remark, Вы писали:

R>>>Там просто тупо давятся все ошибки.


ЮЖ>>Давятся, т.к. на уровне контракта в общем случае невозможно специфицировать все возможные ошибки, которые могут возникнуть в реализации.


R>Вот это я и пытаюсь решить.


Т.е. не только для отладочных целей? Можно аналог errno сделать, как в CRT(MSVC) добавили _doserrno.

errno value is not necessarily the same as the actual error code returned by a system call from the Windows operating systems. To access the actual operating system error code, use the _doserrno variable, which contains this value.

Re[23]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 17:00
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Допустим у меня есть моя реализация библиотеки pthreads, с расширенными функциями.


V>Ты пишешь не о контрактах, а о стандартах.


А разница в данном контексте?


V>Если твоя библиотека реализует некий СТАНДАРТ — то да, не убавить, ни прибавить. Но далеко не все контракты привязаны к стандартам. Кстати, даже в твоем примере, я не согласен.

V>ПОСИКС ориентирован на Nix. Если ты реализуешь кросслпатформенный посикс, умеющий работать в том числе под вин, то да, вполне можно ввести туда дополнительные функции типа get_win_error. В этом случае те, кому нужна чистая кроссплатформенность не будут ее использовать (а могут и использовать, если функция будет уметь закорачивать себя в иных средах), а те, кого интересует только виндовая имплементация — получат преимущества дополнительной диагностики.
V>Так что даже в твоем примере вполне полезно.

Так а чего плохого предоставить какие-то преимущества и тем, кому нужна кросс-платформенность, если альтернатива только не предоставлять никаких преимущуств? Если речь о POSIX, то это — все пользователи. Писать под интерфейс POSIX, но при этом только под Windows, выглядит поменьшей мере странно.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[17]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 17:03
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

R>>>>Там просто тупо давятся все ошибки.


ЮЖ>>>Давятся, т.к. на уровне контракта в общем случае невозможно специфицировать все возможные ошибки, которые могут возникнуть в реализации.


R>>Вот это я и пытаюсь решить.


ЮЖ>Т.е. не только для отладочных целей?


Только для отладочных целей. Не для отладочных тут ничего не сделать, так пусть хоть будет для отладочных.

Можно аналог errno сделать, как в CRT(MSVC) добавили _doserrno.

Нельзя:
http://www.rsdn.ru/forum/cpp/3924339.1.aspx
Автор: remark
Дата: 18.08.10



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[24]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 17:05
Оценка:
R>Так а чего плохого предоставить какие-то преимущества и тем, кому нужна кросс-платформенность, если альтернатива только не предоставлять никаких преимущуств? Если речь о POSIX, то это — все пользователи. Писать под интерфейс POSIX, но при этом только под Windows, выглядит поменьшей мере странно.
Просто тем, кто пользуется позикс в юниксе, никаких преимуществ уже не нужно — подсистемане сможет верунть ничего такого, чтобы не было предусмотрено в позиксе.
Да здравствует мыло душистое и веревка пушистая.
Re[25]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 17:08
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Так а чего плохого предоставить какие-то преимущества и тем, кому нужна кросс-платформенность, если альтернатива только не предоставлять никаких преимущуств? Если речь о POSIX, то это — все пользователи. Писать под интерфейс POSIX, но при этом только под Windows, выглядит поменьшей мере странно.

V>Просто тем, кто пользуется позикс в юниксе, никаких преимуществ уже не нужно — подсистемане сможет верунть ничего такого, чтобы не было предусмотрено в позиксе.

Я рад за них. А остальным что делать?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[26]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 17:13
Оценка:
R>Я рад за них. А остальным что делать?
Остальным — это кому? Тем, кто пользуется твоей библиотекой в средах, не реализующих позикс и предоставляющими дополнительние коды возврата — использовать get_ext_error.
Разве нет?
Да здравствует мыло душистое и веревка пушистая.
Re[27]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 17:17
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Я рад за них. А остальным что делать?


V>Остальным — это кому? Тем, кто пользуется твоей библиотекой в средах, не реализующих позикс и предоставляющими дополнительние коды возврата — использовать get_ext_error.

V>Разве нет?

Млять тем, кто просто пользуется интерфейсом POSIX. Не в средах, а просто. Что б работало и в Unix, и в Windows, и в MacOX.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[28]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 17:18
Оценка:
R>Млять тем, кто просто пользуется интерфейсом POSIX. Не в средах, а просто. Что б работало и в Unix, и в Windows, и в MacOX.

Разве мы не говорили о гипотетичском примере — кроссплатформенной реализации позикс? Я уже потерял нить.
Да здравствует мыло душистое и веревка пушистая.
Re[29]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 17:27
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Млять тем, кто просто пользуется интерфейсом POSIX. Не в средах, а просто. Что б работало и в Unix, и в Windows, и в MacOX.


V>Разве мы не говорили о гипотетичском примере — кроссплатформенной реализации позикс? Я уже потерял нить.


Об этом и говорим. И у такой библиотеки могут быть не только пользователи, которые используют её под юникс, или которые используют её под виндовс. Могут быть и такие, которые используют её и под юникс и под виндовс, да ещё и не хотят отклоняться от интерфейса ПОСИКС.
Они не могут использовать get_ext_error(), но при этом им надо работать и под виндовс.
Вот представь себе. Реальная ситуация.
И это могут быть не только интерфейсы POSIX, но и ISO C/C++, или там какие-нибудь интерфейсы для XML.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[30]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 17:40
Оценка:
R>Об этом и говорим. И у такой библиотеки могут быть не только пользователи, которые используют её под юникс, или которые используют её под виндовс. Могут быть и такие, которые используют её и под юникс и под виндовс, да ещё и не хотят отклоняться от интерфейса ПОСИКС.
Ради бога. Эти пользователи либо откажутся от использования get_ext_error, либо она всегда будет возвращать empty в не-вин средах.

R>Они не могут использовать get_ext_error(), но при этом им надо работать и под виндовс.

См. выше.
Да здравствует мыло душистое и веревка пушистая.
Re[31]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 17:58
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Об этом и говорим. И у такой библиотеки могут быть не только пользователи, которые используют её под юникс, или которые используют её под виндовс. Могут быть и такие, которые используют её и под юникс и под виндовс, да ещё и не хотят отклоняться от интерфейса ПОСИКС.

V>Ради бога. Эти пользователи либо откажутся от использования get_ext_error, либо она всегда будет возвращать empty в не-вин средах.

Я понимаю, что они откажутся. Они скорее всего даже и не будет рассматривать такую возможность. Вот об этом и речь, и что ты им предложишь?
С тем, что я предлагаю, им возможно будет чуточку полегче. По-крайней мере мне лично легче отлаживать — вся информация под рукой.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[32]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 18:08
Оценка:
R>Я понимаю, что они откажутся. Они скорее всего даже и не будет рассматривать такую возможность.

Не понимаю. Почему не будут рассматривать?
Да здравствует мыло душистое и веревка пушистая.
Re[33]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 18:14
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Я понимаю, что они откажутся. Они скорее всего даже и не будет рассматривать такую возможность.


V>Не понимаю. Почему не будут рассматривать?


Не важно, забдуь. Пусть как ты сказал — они просто отказались. Так что ты можешь им предложить?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[34]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 18:18
Оценка:
R>Не важно, забдуь. Пусть как ты сказал — они просто отказались. Так что ты можешь им предложить?
Переехать на Гоа например — и больше никогда ничего не программировать. Что значит "просто отказались"?
Да здравствует мыло душистое и веревка пушистая.
Re[35]: По поводу применимости
От: wander  
Дата: 18.08.10 18:22
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Не важно, забдуь. Пусть как ты сказал — они просто отказались. Так что ты можешь им предложить?

V>Переехать на Гоа например — и больше никогда ничего не программировать. Что значит "просто отказались"?

Честно говоря это уже смахивает на троллинг. Перечитай еще раз ветку, remark там все очень доходчиво объяснил.
Можно взять к примеру реализацию pthreads для win32 и на ее примере просто понять, почему нет смысла использовать расширенные функции, если есть необходимость потом написанное компилировать с настоящим pthreads.
Re[36]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 18:24
Оценка:
W>Честно говоря это уже смахивает на троллинг.
Под кроватью у себя троллей поищи.


W>Можно взять к примеру реализацию pthreads для win32 и на ее примере просто понять, почему нет смысла использовать расширенные функции, если есть необходимость потом написанное компилировать с настоящим pthreads.

Вот я не понял. Объясни, если ты понимаешь.
Да здравствует мыло душистое и веревка пушистая.
Re[37]: По поводу применимости
От: wander  
Дата: 18.08.10 18:28
Оценка:
Здравствуйте, Vamp, Вы писали:

W>>Честно говоря это уже смахивает на троллинг.

V>Под кроватью у себя троллей поищи.
Ни к чему эта агрессия. Я вообще без эмоций писал.

W>>Можно взять к примеру реализацию pthreads для win32 и на ее примере просто понять, почему нет смысла использовать расширенные функции, если есть необходимость потом написанное компилировать с настоящим pthreads.

V>Вот я не понял. Объясни, если ты понимаешь.
Я знаю как работать с pthreads, и не знаю этих расширенных функций. Это как минимум время на их изучение. Еще следует иметь в виду, что при компиляции с настоящими pthreads придется писать #ifdef #endif, чтобы расширенные функции не приводили к ошибке компиляции, потому что их там нет.
Re[38]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 18:31
Оценка:
V>>Под кроватью у себя троллей поищи.
W>Ни к чему эта агрессия. Я вообще без эмоций писал.
Я тоже без эмоций.

W>Я знаю как работать с pthreads, и не знаю этих расширенных функций. Это как минимум время на их изучение.

Ну новую библиотеку придется изучить, как ни крути. Это в любом случае так будет, даже с решением от Ремарка, потому что возвращаются коды ошибок неприменимые в юникс.

W>Еще следует иметь в виду, что при компиляции с настоящими pthreads придется писать #ifdef #endif, чтобы расширенные функции не приводили к ошибке компиляции, потому что их там нет.

Отчего же? Закорачиваться функции будут внутри библиотеки. Тебе ничего делать не надо.
Да здравствует мыло душистое и веревка пушистая.
Re[39]: По поводу применимости
От: wander  
Дата: 18.08.10 18:37
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Ну новую библиотеку придется изучить, как ни крути. Это в любом случае так будет, даже с решением от Ремарка, потому что возвращаются коды ошибок неприменимые в юникс.

Если мы говорим об эмуляции posix threads в win32, то коды должны быть одни и те же. Иначе это уже не эмуляция. И Ремарк писал, что контракт менять нельзя.

V>Отчего же? Закорачиваться функции будут внутри библиотеки. Тебе ничего делать не надо.

Пусть библиотека эмулятор преобразует коды текущей системы, в коды которые соответствуют контракту. А что делать с остальными?
Re[39]: По поводу применимости
От: wander  
Дата: 18.08.10 18:38
Оценка:
Здравствуйте, Vamp, Вы писали:

Все-таки категорически советую еще раз прочитать ветку. В пылу спора возможны неверные оценки.
Re[40]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 18:41
Оценка:
W>Если мы говорим об эмуляции posix threads в win32, то коды должны быть одни и те же. Иначе это уже не эмуляция.
Мы говорим не о эмуляции, а о кроссплатформенной библиотеке, реализующий посикс.

W>И Ремарк писал, что контракт менять нельзя.

А я с ним спорил.

W>Пусть библиотека эмулятор преобразует коды текущей системы, в коды которые соответствуют контракту. А что делать с остальными?

Не путай библиотеку и эмулятор. Остальными кем?
Да здравствует мыло душистое и веревка пушистая.
Re[41]: По поводу применимости
От: wander  
Дата: 18.08.10 18:49
Оценка:
Здравствуйте, Vamp, Вы писали:

W>>Если мы говорим об эмуляции posix threads в win32, то коды должны быть одни и те же. Иначе это уже не эмуляция.

V>Мы говорим не о эмуляции, а о кроссплатформенной библиотеке, реализующий посикс.
Я тоже. У меня есть исходники написанные для c использованием pthreads, я хочу их скомпилировать под win32. Если такая библиотека будет предоставлять отличные коды ошибок (ты об этом сам выше написал) то тут тупо ничего не заработает.
Возможно слово неудачное — эмуляция. Я говорил о библиотеке, которая предоставляет интерфейс, идентичный pthreads. Эмулирует интерфейс. Но термин неудачный, ладно.

W>>Пусть библиотека эмулятор преобразует коды текущей системы, в коды которые соответствуют контракту. А что делать с остальными?

V>Не путай библиотеку и эмулятор.
Я не путаю. Термин неудачный, двусмысленный.

V>Остальными кем?

Чем. Кодами. В данном случае системы win32. Кодами, которые не имеют эквивалента в posix.
Re[41]: По поводу применимости
От: wander  
Дата: 18.08.10 18:58
Оценка:
Здравствуйте, Vamp, Вы писали:

W>>И Ремарк писал, что контракт менять нельзя.

V>А я с ним спорил.

Я сам недавно с таким боролся. У меня был проект, который был написан на С++, юзалась библиотека XML, тоже на С++. Бибоиотека реализовывала модель SAX. Через наследование и определение виртуальных функций можно было задавать обработчики тэгов. В этих обработчиках активно использовались всякие исключения. Так как все было написано на С++ — проблем не было. Проблемы начались тогда, когда потребовалось сменить библиотеку XML c C++ на С. Был написан враппер, который повторял интерфейс той прежней библиотеки. Но встала проблема с исключениями. Исключения в данном случае нарушали контракт. Но старый код, а его очень много, трогать было слишком затратно. То есть решения переделать все на коды ошибок, или изменить архитектуру, что бы обрабатывать все исключения на одном уровне — уровне враппера не катили.
Re[42]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 19:13
Оценка:
W>Я тоже. У меня есть исходники написанные для c использованием pthreads, я хочу их скомпилировать под win32. Если такая библиотека будет предоставлять отличные коды ошибок (ты об этом сам выше написал) то тут тупо ничего не заработает.
Разумеется. Именно по этому функции, определенные в позикс, будут возвращать коды ошибок, определенные в позикс.

W>Чем. Кодами. В данном случае системы win32. Кодами, которые не имеют эквивалента в posix.

Ну я об этом уже четыре часа пишу. Они будут возвращены через get_ext_error.
Да здравствует мыло душистое и веревка пушистая.
Re[36]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 19:13
Оценка:
Здравствуйте, wander, Вы писали:

R>>>Не важно, забдуь. Пусть как ты сказал — они просто отказались. Так что ты можешь им предложить?

V>>Переехать на Гоа например — и больше никогда ничего не программировать. Что значит "просто отказались"?

W>Честно говоря это уже смахивает на троллинг. Перечитай еще раз ветку, remark там все очень доходчиво объяснил.

W>Можно взять к примеру реализацию pthreads для win32 и на ее примере просто понять, почему нет смысла использовать расширенные функции, если есть необходимость потом написанное компилировать с настоящим pthreads.

Ну слава богу, я уже начал думать, что это у меня крыша едет

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[43]: По поводу применимости
От: wander  
Дата: 18.08.10 19:23
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Ну я об этом уже четыре часа пишу. Они будут возвращены через get_ext_error.

Ну мы опять вернулись на исходную позицию. То есть опять же мы переписываем исходники с использованием этой функции, вставляем ее в условную компиляцию, чтобы не мешалась под unix. Так?
Re[44]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 19:40
Оценка:
W>Ну мы опять вернулись на исходную позицию. То есть опять же мы переписываем исходники с использованием этой функции, вставляем ее в условную компиляцию, чтобы не мешалась под unix. Так?
Нет, не так.
Мы добавляем вызов этой функции, если нас интересуют расширенные коды ошибок. Библиотека позаботится о том, чтобы она работала и в других средах.
Да здравствует мыло душистое и веревка пушистая.
Re[45]: По поводу применимости
От: wander  
Дата: 18.08.10 19:57
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Нет, не так.

V>Мы добавляем вызов этой функции, если нас интересуют расширенные коды ошибок. Библиотека позаботится о том, чтобы она работала и в других средах.
Неверно. В другой среде будет не эта библиотека. А настоящий pthreads. Эта библиотека используется только в win32, чтобы дать возможность скомпилироваться юниксовым исходникам.
exception C00000FD
От: rm822 Россия  
Дата: 18.08.10 20:17
Оценка: :))
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[46]: По поводу применимости
От: Vamp Россия  
Дата: 18.08.10 21:09
Оценка:
W>Неверно. В другой среде будет не эта библиотека. А настоящий pthreads. Эта библиотека используется только в win32, чтобы дать возможность скомпилироваться юниксовым исходникам.
А так работать не будет. Если у тебя в другой среде нет этой библиотеки, то include <pthreads_lib.h> отвалится с ошибкой. Или как?
Да здравствует мыло душистое и веревка пушистая.
Re[2]: По поводу применимости
От: SpaceConscience  
Дата: 18.08.10 21:13
Оценка:
А все-таки можно посмотреть кусок реального кода, где такое используется?

Просто я, например, до сих пор не применял такую мощную проверку ошибок (чтобы даже у CloseHandle ошибку проверять).

Дело не в самом unused<T>, хоть мне и показалось, что он против KISS, просто для меня непривычна такая плотность проверки ошибок, что даже приходится вводить специальные конструкции для этого.
Собрался ставить минус? Да сам иди в жопу!

































































.
Re[3]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 18.08.10 21:33
Оценка:
Здравствуйте, SpaceConscience, Вы писали:

SC>А все-таки можно посмотреть кусок реального кода, где такое используется?


SC>Просто я, например, до сих пор не применял такую мощную проверку ошибок (чтобы даже у CloseHandle ошибку проверять).


SC>Дело не в самом unused<T>, хоть мне и показалось, что он против KISS, просто для меня непривычна такая плотность проверки ошибок, что даже приходится вводить специальные конструкции для этого.



Если бы это был С++, и поставлялось в исходных кода, то наверное тут бы пригодилось; а так это С89 и без исходных кодов, поэтому тут приходится по старинке.
RL_API int rl_thread_create(rl_thread_t* thr, rl_thread_start_t func, void* arg, rl_thread_prio_t prio, size_t stack_size)
{
    rl_thread_impl_t*           impl;
    DWORD                       werr;
    int                         err;
    int                         win_prio;

    if (thr == 0 || func == 0)
        return RL_ERR_INVALID_ARG;

    if (stack_size > UINT_MAX)
        stack_size = UINT_MAX;
    impl = (rl_thread_impl_t*)malloc(sizeof(rl_thread_impl_t));
    if (impl == 0)
        return RL_ERR_NOMEM;
    thr->impl = impl;
    impl->func = func;
    impl->arg = arg;
    impl->res = 0;
    rl_atomic_size_store(&impl->rc, 2, rl_memory_order_nonatomic);
    impl->handle = (HANDLE)_beginthreadex(0, (unsigned)stack_size, rl_thread_func, impl, 0, 0);
    if (impl->handle == 0 || (uintptr_t)impl->handle == (uintptr_t)-1)
    {
        err = errno;
        (void)err;
        assert(!"failed to start a thread");
        free(impl);
        return RL_ERR_OTHER;
    }
    if (prio != rl_thread_prio_normal)
    {
        win_prio = THREAD_PRIORITY_NORMAL;
        if (prio == rl_thread_prio_lowest)
            win_prio = THREAD_PRIORITY_LOWEST;
        else if (prio == rl_thread_prio_low)
            win_prio = THREAD_PRIORITY_BELOW_NORMAL;
        else if (prio == rl_thread_prio_high)
            win_prio = THREAD_PRIORITY_ABOVE_NORMAL;
        else if (prio == rl_thread_prio_highest)
            win_prio = THREAD_PRIORITY_HIGHEST;
        if (0 == SetThreadPriority(impl->handle, win_prio))
        {
            werr = GetLastError();
            (void)werr;
            assert(!"failed to set thread's priority");
        }
    }
    return 0;
}




RL_API int rl_thread_detach(rl_thread_t thr)
{
    rl_thread_impl_t*           impl;
    DWORD                       err;

    if (thr.impl == 0)
        return RL_ERR_INVALID_ARG;

    impl = (rl_thread_impl_t*)thr.impl;
    if (FALSE == CloseHandle(impl->handle))
    {
        assert(!"failed to close thread's handle");
        err = GetLastError();
        (void)err;
        return RL_ERR_OTHER;
    }
    if (1 == rl_atomic_size_fetch_sub(&impl->rc, 1, rl_memory_order_relaxed))
        free(impl);
    return 0;
}




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: По поводу применимости
От: Юрий Жмеренецкий ICQ 380412032
Дата: 19.08.10 02:54
Оценка:
Здравствуйте, SpaceConscience, Вы писали:

SC>Дело не в самом unused<T>, хоть мне и показалось, что он против KISS, просто для меня непривычна такая плотность проверки ошибок, что даже приходится вводить специальные конструкции для этого.


Специальные конструкции он вводит не для проверок ошибок (она и так присутствует), а в целях диагностики.
Пример в первом посте неудачный.
Re[4]: По поводу применимости
От: uzhas Ниоткуда  
Дата: 19.08.10 06:52
Оценка:
Здравствуйте, remark, Вы писали:

R>Если бы это был С++, и поставлялось в исходных кода, то наверное тут бы пригодилось; а так это С89 и без исходных кодов, поэтому тут приходится по старинке.

R>
R>RL_API int rl_thread_create(rl_thread_t* thr, rl_thread_start_t func, void* arg, rl_thread_prio_t prio, size_t stack_size)
R>


мое скромное мнение: все ассерты вырезать и убрать неиспользуемые переменные
библиотека пишется не для того, чтобы ее дебужили, а для того, чтобы ею пользовались
если моя программа будет выходить (exit) из-за какого-то ассерта в библиотеке, то я буду недоволен
а поставить бряку на return OTHER_ERR я всегда смогу при надобности
главное, что возвращается код ошибки ERR_OTHER, у клиента есть возможность анализировать ошибку
да, в этом коде недостаточно информации, но это общая беда ретурн кодов. при желании можно сразу проектировать более дескриптивные коды:
struct ReturnCode
{
  string message;
  int code;
};

зы: сорри, весь тред не читал, много букв
Re[5]: По поводу применимости
От: remark Россия http://www.1024cores.net/
Дата: 19.08.10 08:05
Оценка:
Здравствуйте, uzhas, Вы писали:

R>>Если бы это был С++, и поставлялось в исходных кода, то наверное тут бы пригодилось; а так это С89 и без исходных кодов, поэтому тут приходится по старинке.

R>>
R>>RL_API int rl_thread_create(rl_thread_t* thr, rl_thread_start_t func, void* arg, rl_thread_prio_t prio, size_t stack_size)
R>>


U>мое скромное мнение: все ассерты вырезать и убрать неиспользуемые переменные

U>библиотека пишется не для того, чтобы ее дебужили, а для того, чтобы ею пользовались

Ну в начале-то её надо заставить работать. А потом постоянно убеждаться, что она не сломалась.


U>если моя программа будет выходить (exit) из-за какого-то ассерта в библиотеке, то я буду недоволен

U>а поставить бряку на return OTHER_ERR я всегда смогу при надобности

Из-за ассёрта не вылетит, и бряку ты поставить не сможешь — поставляется релиз сборка без исходных кодов. Это всё для разработчика библиотеки.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.