Pull to refresh
2
0
amosk @amosk

User

Send message
Так и CHAI_IMPORT тоже макрос ))
C++ обертки для Lua
github.com/vapourismo/luwra

Обертка класса выглядит даже проще чем обертки для ChaiScript
Для шаблонизации регулярных структур можно намного более читаемый подход использовать.

#define DEFINE_ENUM_MEMBER(name) name,
#define DEFINE_ENUM(name, list) enum name { \
    list(DEFINE_ENUM_MEMBER) \
    };

#define DEFINE_ENUM_CASE(name) case name: return #name;
#define DEFINE_ENUM_TO_STRING(name, list) \
    const char* name ## _tostring(name v) { \
        switch (v) { \
            list(DEFINE_ENUM_CASE) \
        } \
        return "?"; \
    }

// user code

#define enum_test1(handler)\
    handler(field1) \
    handler(field2) \

DEFINE_ENUM(test1, enum_test1)
DEFINE_ENUM_TO_STRING(test1, enum_test1)

int main()
{
    LOG_TRACE(test1_tostring(field1));
    return 0;
}


Тут применяется возможность передать имя макроса в качестве параметра в другой макрос.
#define PR(f, ...) printf(f, __VA_ARGS__) 

Такой стиль поддерживают более менее все.
Конечно не Coroutines TS — их я критикую в своем комменте.
А эти я привел как пример того, что можно все сделать проще, если стоит задача асинхронный код сделать «синхронным» по форме.
Как-то слишком много синтаксического мусора.

В Asio можно намного проще корутины использовать. Неявно.

boost::asio::spawn(io_service, [socket] (boost::asio::yield_context y)) {
    socket.async_read(buffer, y);
    socket.async_write(buffer, y);
});
Извините, что без классов ))
Извините, что без монад :)
/*
 *   s e n d
 * + m o r e
 * ---------
 * m o n e y
 *
 */

bool digits[10] = {0};
char letters[8] = {'s', 'e', 'n', 'd', 'm', 'o', 'r', 'y'};
int result[8] = {};
int& s = result[0];
int& e = result[1];
int& n = result[2];
int& d = result[3];
int& m = result[4];
int& o = result[5];
int& r = result[6];
int& y = result[7];

void print()
{
    cout << "  " << s << " " << e << " " << n << " " << d << endl;
    cout << "+ " << m << " " << o << " " << r << " " << e << endl;
    cout << "---------" << endl;
    cout << m << " " << o << " " << n << " " << e << " " << y << endl;
}

bool solve(int letter)
{
    if (letter == sizeof(letters)) {
        if (m == 0 || s == 0)
            return false;
        bool solved =
                (((s * 10 + e) * 10 + n) * 10 + d)
                +
                (((m * 10 + o) * 10 + r) * 10 + e)
                ==
                ((((m * 10 + o) * 10 + n) * 10 + e) *10 + y);
        return solved;
    }

    for (int i = 0; i < 10; i++) {
        if (digits[i]) continue;
        digits[i] = 1;
        result[letter] = i;
        if (solve(letter + 1))
            return true;
        digits[i] = 0;
    }
    return false;
}

int main()
{
    if (solve(0)) {
        print();
    }
    return 0;
}
A race condition or race hazard is the behavior of an electronic or software system where the output is dependent on the sequence or timing of other uncontrollable events.


Т.е. буквально то что происходит при копировании в один буфер из нескольких потоков.

Действительно. Причем тут ядро? Где у меня про ядро в комменте про memcpy?
Нет. Наоборот.
Мой пример доказывает, что потокобезопасность по POSIX не гарантирует отсутствие race condition.
А именно race condition и является причиной наблюдаемого поведения.
Касательно мьютекса в сокете — почитайте исходники линукса.
У вас есть возражения против того что оба эти условия выполняются?
1) memcpy потокобезопасна по POSIX
2) memcpy не потокобезопасна при передаче одного и того же буфера из разных потоков
Я не знаю где описано.
Поэтому привел простой и понятный пример (memcpy) подтверждающий мои слова.
Вызов из двух потоков некорректен.
А мьютекс там нужен, чтобы ядро могло защититься от дураков и сохранить внутренние структуры в консистентном состоянии.
Совсем не обязательно что после такой защиты вы получите хоть какой-то полезный или повторяемый результат.
Вы неверно понимаете что имеется в виду под thread-safe в POSIX.

Например memcpy потокобезопасна с точки зрения POSIX.
То есть ее ВООБЩЕ можно вызывать из нескольких потоков одновременно.

Однако вызов из двух потоков с одним и тем же приемным буфером не является потокобезопасным.

Точно по той же причине, одновременный вызов read для одного и того же дескриптора из разных потоков тоже не является безопасным, хотя read сама по себе потокобезопасна.
Там не юзерский мьютекс, а ядерный, специально спроектированный для работы с сокетом.

А вообще, да, расскажите, что происходит, если из обработчика сигнала вызвать read, а данных еще нет :)
Тут нет инфы достойной отдельной статьи.

Как выше написал encyclopedist:
1) If CLONE_FILES is set, the calling process and the child process share the same file descriptor table
2) в glibc в функции create_thread используестся такой набор флагов ...CLONE_FILES…

Т.е. ничего не клонируется.
Вопрос закрыт.
Мы уже показали что при вызове join() состояния сокетов синхронизируются.

Все что мой код выше показывает — это то что если сокеты применять потокобезопасно (как и следует), то никаких таких «эффектов», которые вы себе придумали — нет.
А когда нет потокобезопасности (как в вашем первом примере) — это обычный undefined behaviour. Утверждать что либо для такого кода бессмысленно.
1
23 ...

Information

Rating
Does not participate
Location
Одесса, Одесская обл., Украина
Registered
Activity