问题描述
我有两个线程(thrd_t
):一个主线程处理事件
和一个使用 fgetwc
等待终端输入的子线程。
#include <threads.h> // mtx_t,mtx_lock,mtx_unlock
#include <wchar.h> // fgetwc,fgetwc_unlocked
FILE* f = (FILE*) p2;
mtx_t* m = (mtx_t*) p1;
volatile sig_atomic_t* i = (volatile sig_atomic_t*) p0;
mtx_lock(m);
volatile wint_t c = fgetwc(f);
if (c != WEOF) {
ungetwc(c,f);
copy_integer(p0,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
}
mtx_unlock(m);
while (*i != *FALSE_BOOLEAN_STATE_CYBOI_MODEL);
由于我想读取ansi转义码序列(三个字符),
终端不得在每个字符后阻塞,因此
在主线程中使用 t.c_cc[VMIN]=0
设置为非阻塞。
检测到序列后,我将终端重置为阻塞
使用 t.c_cc[VMIN]=1
,以便子线程在 fgetwc
处阻塞
直到检测到下一个输入。
mtx_t* m = (mtx_t*) p3;
int* i = (int*) p2;
// The loop break flag.
int b = *FALSE_BOOLEAN_STATE_CYBOI_MODEL;
// The escape character flag.
int esc = *FALSE_BOOLEAN_STATE_CYBOI_MODEL;
int aec = *FALSE_BOOLEAN_STATE_CYBOI_MODEL;
// The input character.
wint_t c = WEOF;
mtx_lock(m);
// Set unblocking mode in terminal.
edit_service(p4,(void*) FALSE_BOOLEAN_STATE_CYBOI_MODEL,(void*) TERMINAL_CYBOI_CHANNEL);
while (*TRUE_BOOLEAN_STATE_CYBOI_MODEL) {
if (b != *FALSE_BOOLEAN_STATE_CYBOI_MODEL) {
break;
}
read_unix_terminal_character(p0,p1,(void*) &b,(void*) &esc,(void*) &aec,(void*) &c);
}
// Set blocking mode in terminal. VMIN = 1
edit_service(p4,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL,(void*) TERMINAL_CYBOI_CHANNEL);
// Reset interrupt request in input/output entry.
copy_integer(i,(void*) FALSE_BOOLEAN_STATE_CYBOI_MODEL);
mtx_unlock(m);
问题:有时,fgetwc
会阻塞,有时不会。
当读入一个字符序列(三个字符)时,
阅读循环留在第三个字符处
子线程块很好。
当读取单个字符时,它的结尾会被检测到
跟随WEOF
,但子线程不再阻塞,
即使t.c_cc[VMIN]=1
。
wint_t* c = (wint_t*) p5;
int* aec = (int*) p4;
int* esc = (int*) p3;
FILE* f = (FILE*) p1;
*c = fgetwc(f);
if (*c != WEOF) {
if (*aec == *TRUE_BOOLEAN_STATE_CYBOI_MODEL) {
// The character sequence ESC[ was received before.
// This is the beginning of an ansi escape code sequence.
// Reset ansi escape code flag.
copy_integer(p4,(void*) FALSE_BOOLEAN_STATE_CYBOI_MODEL);
// Append source character to destination item.
// This is the actual ansi escape code.
modify_item(p0,p5,(void*) WIDE_CHaraCTER_TEXT_STATE_CYBOI_TYPE,(void*) PRIMITIVE_STATE_CYBOI_MODEL_COUNT,*NULL_POINTER_STATE_CYBOI_MODEL,(void*) VALUE_PRIMITIVE_STATE_CYBOI_NAME,(void*) APPEND_MODIFY_LOGIC_CYBOI_FORMAT);
// Set loop break flag.
// All values have been received,so that the loop can be left Now.
copy_integer(p2,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
} else if (*esc == *TRUE_BOOLEAN_STATE_CYBOI_MODEL) {
// The escape character ESC was received before.
// This might be the beginning of an ansi escape code.
// Reset escape character flag.
copy_integer(p3,(void*) FALSE_BOOLEAN_STATE_CYBOI_MODEL);
if (*c == *((wint_t*) LEFT_SQUARE_BRACKET_UNICODE_CHaraCTER_CODE_MODEL)) {
// The escape character ESC received before
// is followed by an opening square bracket [.
// This is the beginning of an ansi escape code.
// Set ansi escape code flag.
copy_integer(p4,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
// Append source character to destination item.
modify_item(p0,(void*) APPEND_MODIFY_LOGIC_CYBOI_FORMAT);
} else {
// The escape character ESC received before
// is followed by another,second character
// which is NOT an opening square bracket.
// This is NOT going to be an ansi escape code sequence.
// Unread this character so that it may be
// processed once more later on.
ungetwc(*c,f);
// Set loop break flag.
copy_integer(p2,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
}
} else if (*c == *((wint_t*) ESCAPE_UNICODE_CHaraCTER_CODE_MODEL)) {
// The escape character ESC was received.
// This might be the beginning of an ansi escape code.
// Set escape character flag.
copy_integer(p3,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
// copy source character to destination character array.
modify_item(p0,(void*) APPEND_MODIFY_LOGIC_CYBOI_FORMAT);
} else {
// No special characters have been found.
// So this is a normal source character
// that is just copied to the destination.
// copy source character to destination character array.
modify_item(p0,(void*) APPEND_MODIFY_LOGIC_CYBOI_FORMAT);
// CAUTION! Do NOT set loop break flag here.
// More than just one character might have to be
// received in a sequence,e.g. an ansi escape code.
// In this case,only a WEOF will break the loop.
}
} else {
// Set loop break flag.
copy_integer(p2,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
}
termios c_cc[VMIN] 值是否可能被缓存而不是从共享内存中读取?
在此处查找项目和所有源代码: https://savannah.nongnu.org/svn/?group=cybop
可能相关: Does making reference variable volatile,make all its field volatile too in java? “...对象不是变量。...所有线程看到相同的引用, 并不是因为它们的内部内容观察到相同的值。”
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)