Показаны сообщения с ярлыком win32. Показать все сообщения
Показаны сообщения с ярлыком win32. Показать все сообщения

пятница, 11 июня 2010 г.

Макрос _T при переносе Win32 проектов на iPhone

Как правило сейчас уже во всех Win32 (MFC) проектах такая строка в коде _T("Я люблю вас, девочки") воспринимается компилятором как L"Я люблю вас, девочки" (то есть как wchar_t строка).

Чтобы не перелопачивать код, который вам нужно портировать из Windows в iPhone, можете добавить в общий заголовочный файл (например, в исходники, где определены все макросы и константы) такое макроопределение:

#ifdef __IPHONE_3_1
#ifndef _T
#define _T(a) L##a
#endif
#endif


После этого вам должно стать хорошо и приятно :)

среда, 2 июня 2010 г.

Проблемы с isnan функцией (при портировании кода Win32-приложения для iPhone)

Функции _isnan нет в iPhone OS (там должна быть функция isnan, включенная в math.h или cmath заголовки), поэтому я делаю такой трюк:

// где-то наверху файла
#ifdef __IPHONE_3_1
#include < cmath > // или #include < math.h >
#endif

// где-то в коде
#ifdef _WIN32
if(_isnan(val))
#elif defined(__IPHONE_3_1)
if (isnan(val))
#endif

//////////////////////////////////
// увы, иногда < cmath > или < math.h > бессильны нам помочь (мистика?),
// и тогда делайте так в одном месте, где-нибудь в общем заголовке:

#ifdef __IPHONE_3_1
#define _isnan(x) \
( sizeof (x) == sizeof(float ) ? __inline_isnanf((float)(x)) \
: sizeof (x) == sizeof(double) ? __inline_isnand((double)(x)) \
: __inline_isnan ((long double)(x)))
#endif //__IPHONE_3_1


Если вы хотите, чтобы #ifdef __IPHONE_3_1 условие точно срабатывало, то один из способов гарантировать это - сделать cpp файл типом objcpp (в свойствах файла, если щёлкнуть по имени файла в дереве Xcode-проекта). С заголовочными файлами обстоит немного посложнее, но если заголовочник уже включен в cpp-файл, с которым вы сделали как я советую, то обычно всё в порядке будет и в заголовочном файле.

пятница, 21 мая 2010 г.

Аналог Sleep (Win32) функции в Mac OS (iPhone OS)

Материал взят из http://www.gamedev.ru/code/forum/?id=92177

Названия функций я поменял, чтобы уменьшить вероятность конфликта имён.

Спасибо разработчикам QT.



#ifndef QTSLEEP_H
#define QTSLEEP_H

#include <pthread.h>
#include <sys/time.h>

static void qt_thread_sleep(struct timespec *ti)
{
pthread_mutex_t mtx;
pthread_cond_t cnd;

pthread_mutex_init(&mtx, 0);
pthread_cond_init(&cnd, 0);

pthread_mutex_lock(&mtx);
(void) pthread_cond_timedwait(&cnd, &mtx, ti);
pthread_mutex_unlock(&mtx);

pthread_cond_destroy(&cnd);
pthread_mutex_destroy(&mtx);
}

void qt_sleep(unsigned long secs)
{
struct timeval tv;
gettimeofday(&tv, 0);
struct timespec ti;
ti.tv_sec = tv.tv_sec + secs;
ti.tv_nsec = (tv.tv_usec * 1000);
qt_thread_sleep(&ti);
}

void qt_msleep(unsigned long msecs)
{
struct timeval tv;
gettimeofday(&tv, 0);
struct timespec ti;

ti.tv_nsec = (tv.tv_usec + (msecs % 1000) * 1000) * 1000;
ti.tv_sec = tv.tv_sec + (msecs / 1000) + (ti.tv_nsec / 1000000000);
ti.tv_nsec %= 1000000000;
qt_thread_sleep(&ti);
}

void qt_usleep(unsigned long usecs)
{
struct timeval tv;
gettimeofday(&tv, 0);
struct timespec ti;

ti.tv_nsec = (tv.tv_usec + (usecs % 1000000)) * 1000;
ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (ti.tv_nsec / 1000000000);
ti.tv_nsec %= 1000000000;
qt_thread_sleep(&ti);
}

#endif

вторник, 27 апреля 2010 г.

Какой аналог у SetEvent (Win32) в pthread?

Материал взят из http://electronix.ru:1288/forum/lofiversion/index.php/t47683.html

Andrey Sudnov
May 13 2008, 11:36
Проблема в том, что в библиотеке PThread нет работы с файловыми дескрипторами. Соответственно, для того чтобы одновременно ожидать завершения какой-либо файловой (или сокетовой) операции или поступления управляющего сигнала от другого потока (например, об отмене операции), приходится использовать неименнованные каналы (pipe и write, вместо SetEvent) и функцию poll (предпочитаю ее, а не select). Перерыл кучу книг, в том числе POSIX стандарт, ничего лучше не придумал. Насколько такое решение накладно по ресурсам? Как организовать такое взаимодействие потоков другим способом?
KRS
May 14 2008, 11:38
в POSIX есть mutex и Condition Variables
я когда игрался с POSIX под сигвин делал примерно так:

typedef struct {
pthread_mutex_t lock;
pthread_cond_t event;
bool flag;
}event_t;

static inline void event_init(event_t* event)
{
pthread_mutex_init(&event- >lock,0);
pthread_cond_init(&event- >event,0);
event- >flag=false;
}

static inline void event_set(event_t* event)
{
pthread_mutex_lock(&event- >lock);
if (!event- >flag) {
event- >flag=true;
pthread_cond_signal(&event- >event);
}
pthread_mutex_unlock(&event- >lock);
}

static inline bool event_wait(event_t* event, unsigned s_timeout)
{
bool r;
pthread_mutex_lock(&event- >lock);
if(!event- >flag) {
if (s_timeout) {
timespec_t timer;
clock_gettime(CLOCK_REALTIME,&timer);
timer.tv_sec+=s_timeout;
pthread_cond_timedwait(&event- >event,&event- >lock,&timer);
}else {
do {
pthread_cond_wait(&event- >event,&event- >lock);
}while(!event- >flag);
}
}
r=event- >flag;
event- >flag=false;
pthread_mutex_unlock(&event- >lock);
return r;
}
RCray
May 15 2008, 12:05
да. это даже лучше, чем poll, который не для всех устройств реализован. к тому же в вашем коде подчерпнул кое-что для себя, спасибо.
RCray
May 15 2008, 13:23
только у меня так:


void* child_func(void* arg)
{
struct args_t* args = (args*)arg;

args- >size = read(args- >fd, args- >packet, args- >supposed_size);
args- >event.flag = 1;
pthread_cond_signal(&args- >event.event);

return 0;
}

int parent(struct args_t *args)
{
pthread_t child;
struct timespec tm;

if ( pthread_create(&child, NULL, child_func, args) != 0 )
return ERR_CREATE;

// задание таймаута
...

while(!args- >event.flag)
{
res = pthread_cond_timedwait(&args- >event.event, &args- >event.lock, &tm);
if (res == ETIMEDOUT)
return ERR_TIMEOUT;
}

args- >event.flag = 0;
return args- >errors;
}

KRS
May 15 2008, 15:31
Без mutex есть потенциальные проблемы:
если между проверкой и очисткой возникнет еще одно событие вы его потеряете потому что обнулите args- >event.flag = 0;

(2b|!2b?.. @ May 15 2008, 14:08) [snapback]411551[/snapback]


while(!args- >event.flag)
{
res = pthread_cond_timedwait(&args- >event.event, &args- >event.lock, &tm);
if (res == ETIMEDOUT)
return ERR_TIMEOUT;
}

args- >event.flag = 0;
return args- >errors;
}



RCray
May 15 2008, 15:59
(KRS @ May 15 2008, 16:16) [snapback]411655[/snapback]

Без mutex есть потенциальные проблемы:
если между проверкой и очисткой возникнет еще одно событие вы его потеряете потому что обнулите args- >event.flag = 0;


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

res = pthread_cond_timedwait(&args- >event.event, &args- >event.lock, &tm);
if (res == ETIMEDOUT)
{
pthread_cancel(созданный ранее поток, от которого ожидается сигнал);
return ERR_TIMEOUT;
}

Andrey Sudnov
May 18 2008, 07:14
Не нахожу ответа на свой вопрос... Уточняю условие.
Можно использовать poll, можно select, разницы нет, дело вкуса. Проблема в том, что БЕЗ этих функций невозможно отследить окончание операции с файлом (read, write, recv, send, conect, etc...).
Ситуация следующая. Есть два потока. Один - интерфейс, и там есть кнопка Exit. Другой - работа с сокетами. Работа с сокетами должна быть немедленно прекращена, как только нажали кнопку Exit. Для этого необходимо ждать одновременно и файловый дескриптор (poll/select) и event от pthread (если мы работаем через них). Это невозможно - нет такой функции. В Windows есть такой тип: HANDLE. Он общий и для событий (SetEvent) и для дескрипторов ввода/вывода. Соответственно, оба можно одновременно передать в функцию WaitForMultipleObjects.
Вижу два варианта. Первый: вызывать poll/select с установленным таймаутом в несколько миллисекунд, затем проверять событие и так по кругу. С кнопкой это конечно прокатит, но в случае жесткого реального времени задержка на обработку события будет составлять именно этот таймаут. К тому же постоянное верчение в юзеровском коде не делает чести с точки зрения использования ресурсов и производительности.
Второй вариант: отказаться от синхронизирующих функций pthread нафиг. Использовать pipe. Здесь встает вопрос, насколько эффективно реализованы эти каналы в коде ОС/libc. И не перекрывает ли потенциальная кривая реализация преимуществ над первым вариантом?
Варианты еще?
vshemm
May 18 2008, 17:31
(Andrey Sudnov @ May 18 2008, 07:59) [snapback]412873[/snapback]

Второй вариант: отказаться от синхронизирующих функций pthread нафиг. Использовать pipe. Здесь встает вопрос, насколько эффективно реализованы эти каналы в коде ОС/libc. И не перекрывает ли потенциальная кривая реализация преимуществ над первым вариантом?

А ОС, собственно, какая?
Впрочем, если не нравятся пайпы, можно использовать сокеты smile.gif Для них есть высокоэффективная реализация оповещения об изменении состояния, правда, механизмы в разных ОС разные. Гляньте сюда - http://monkey.org/~provos/libevent/
Так или иначе, задержки будут намного меньше таймаута в неск. миллисекунд при небольшом количестве сокетов.

Варианты еще?

Сигналы?

А вот что пишет Steven Grimm (http://monkeymail.org/archives/libevent-users/2007-January/000450.html):

no UNIX-ish system I'm aware of has an equivalent to the Windows
WaitForMultipleObjects API that allows you to wake up on semaphores /
condition variables and on input from the network. Without that, any
solution is going to end up using pipes (or maybe signals, which have
their own set of issues in a multithreaded context) to wake up the
libevent threads.

однако, про локальные сокеты он почему-то не упоминает.

И еще smile.gif Вы зря,имхо, предпочитаете poll select'у, т.к. poll при каждом вызове гоняет структу в ядро = > большой оверхед. С другой стороны селект имеет ограничени на кол-во дескрипторов. Во всяком случае в linux это так, поэтому и появился epoll().

Pthread Condition Variables и Windows Events (Креатив)

Материал взят из http://mejedi.livejournal.com/27180.html

Две такие похожие истории...

* Condition Variables
Жили-были процессы и была у них на всех одна открывашка. Когда процесс хочет выпить пива, он хватает открывашку. Если после этого процесс обнаруживает, что открывать ему нечего, он скрепя сердце возвращает открывашку и встает в одну из очередей.

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

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

2. pthread_cond_broadcast()
Приходит добрый дядька, приносит всем процессам в очереди по пиву, и уходит. Процессы наперегонки бегут хватать открывашку.

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

* Events
Жили были процессы и была у каждого своя открывашка. Когда процессы хотят выпить пива, они выстраиваются в очереди. Очередь обслуживают двое дядек с очень разными характерами – Manual Reset Дядько и Auto Reset Дядько.

M.R. Дядько очень терпеливый. Он выдает всем стояльцем в очереди по пиву, и ждет чтобы кто-нибудь пришел еще. Всем новоприбывшим Дядько тоже дает пиво. Если управляющий не отзовет дядьку, он так и будет бесконечно всем давать пиво.

A.R. Дядько тоже терпеливый. Если он пришел – а в очереди никого, он подождет. С собой у Дядько только одна бутылка, поэтому он уйдет как только отдаст её первому процессу в очереди.

1. SetEvent()
Позвать дядьку.

2. ResetEvent()
Прогнать дядьку.

3. PulseEvent()
Управляющей звонит дядьке и говорит чтобы он принес пива. Потом перзванивает, и говорит что передумал. Потом звонит снова и говорит что пиво всё-таки надо нести. И так много раз. Дядька может сойти с ума и всех поубивать.


Между ними нет ничего общего. Auto Reset Event и pthread_cond_signal() ничем не похожи. Manual Reset Event не имеет никакого отношения к бродкастам. Отличия в самой модели. Pthread Condition Variables мгновенны, а Windows Events инерционны.

Когда сигналится condition variable, создается мгновенный и актуальный список ожидающих на c/v процессов. Далее пробуждаются или все процессы или только первый. Из-за этой мгновенности c/v всегда используется только вместе с мьютексом, чтобы не прозевать событие, которое сигналится с помощью c/v.

Семантика такова – pthread_cond_wait() принимает указатель на c/v и залоченный мьютекс. Затем атомарно разлочивается мьютекс и процесс ждет пока c/v не будет просигналена. Наконец мьютекс захватывается снова, и pthread_cond_wait() завершается. Предполагается, что если c/v просигналена пока процесс держит мьютекс, это можно безопасно проигнорировать. Обычно это на самом деле так, потому что используется мьютекс, который защищает структуру данных, изменение состояния которой сигналится с помощью c/v. Если мы взяли мьютекс, то можем спокойно проверить данные на предмет соответствия интересующему нас состоянию. Классический пример – защищенная мьютексом очередь сообщений и c/v, которая сигналится при каждом помещении собщения в очередь.

Напротив, в ОС Windows невозможно сформировать актуальный список процессов, ожидающих на определенном объекте. В процесс может быть доставлена kernel-mode APC, после чего процесс временно покинет состояние ожидания. Второй источник инерционности – это семантика функции WaitForMultipleObjects(bWaitAll=TRUE). Процесс не покинет состояние ожидания до тех пор, пока все объекты не перейдут в signaled state. Концепция этого самого signaled state напрямую диктует, что примитивы синхронизации инерционны. Объект может потерять signaled state если разблокируется ожидающий на нем процесс, просто так потерять signaled state нельзя.

Бесполезно передергивать Auto Reset Event чтобы достичь эффекта бродкаста. Manual Reset Event также бесполезно передергивать. Попытка сделать это вручную – SetEvent(); ResetEvent(); – также не даст результатов. Нет гарантий, что в промежутке между установкой и сбросом события кто-то успеет заметить изменение состояния события и разблокируется.

Это конечно не значит, что conditional variable нельзя сделать в Windows. Очевидно, придется собирать conditional variable из нескольких независимых примитивов синхронизации. Её не получится использовать в WaitForMultipleObjects() совместно с другими объектами синхронизации.

Постоянные читатели