Lag using Xlib/X11 event handling in C - c

Beginner user of C here.
I'm trying to build a library in C using X11/Xlib so I can use it just for little projects and I'm running into a problem when trying to handle events to get input(button presses and key presses) from the user. It works fine for a while and then it starts to build up a significant lag over time.
Right now what I have is my program checking if there is an event waiting and if there is, retrieving it.
I think that my problem right now is that the events are getting stored in memory and its bogging down the program. But that's just a total guess.
Any help will be appreciated. Thank you.
EDIT: Forgot code (I knew I forgot something)
The two functions in question are:
int event_waiting()
{
XEvent event;
if(XCheckMaskEvent(dspy,-1,&event)) {
if(event.type==KeyPress) {
XPutBackEvent(dspy,&event);
return 1;
} else if (event.type==ButtonPress) {
XPutBackEvent(dspy,&event);
return 1;
}
} /* <<=== added missing close-curly here */
return 0;
}
char wait()
{
XEvent event;
XNextEvent(dspy,&event);
if(event.type==KeyPress) {
saved_x = event.xkey.x;
saved_y = event.xkey.y;
return XLookupKeysym(&event.xkey,0);
} else if(event.type==ButtonPress) {
saved_x = event.xkey.x;
saved_y = event.xkey.y;
return event.xbutton.button;
}
}
And then they are called in the main like so,
if (event_waiting()){
char c = wait();
//Switch case goes here
}
EDIT 2: UPDATED CODE
XEvent event;
if(XCheckMaskEvent(display,-1,&event))
{
if(event.type==KeyPress) {
XPutBackEvent(display,&event);
return 1;
} else if (event.type==ButtonPress) {
XPutBackEvent(display,&event);
return 1;
}
}
XFlush(display);
return 0;
`

The lag, which gets worse over time, means that you have many untouched events in your event queue, which slows down XCheckMaskEvent().
Try specifying events using XSelectInput(... ButtonPressMask | KeyPressMask), and try flushing the event queue using XFlush() if there is no event in which you are interested:
if(event.type==KeyPress) {
XPutBackEvent(dspy,&event);
return 1;
} else if (event.type==ButtonPress) {
XPutBackEvent(dspy,&event);
return 1;
} else {
XFlush(dspy); // this
}

Related

C: Bus Error between function returns and execution goes back to parent function

To simplify the problem as much as possible, I have two functions, a parent that calls the child. Everything executes okay till it gets to the return of the child function. After that I get a Bus Error.
int main () {
game();
// this doesn't get executed and program fails with bus error
printf("Execute 2");
return 1;
}
int game () {
game_t GameInfo = {.level = 1, .score = 0, .playerCh = 0, .playerX = 1, .playerY = 1};
gameLevel(&GameInfo);
mvprintw(1,1, "Executed");
// code works up to here and get's executed properly
return 1;
};
void gameLevel (game_t *GameInfo) {
// determine the size of the game field
int cellCols = COLS / 3;
int cellRows = (LINES / 3) - 2;
GameInfo -> playerX = 1;
GameInfo -> playerY = 1;
generateMaze(0);
int solved = 0;
int level = GameInfo -> level;
// default player position
getPlayerDefault(GameInfo);
pthread_t enemies_th;
pthread_create(&enemies_th, NULL, enemies, (void *)GameInfo);
// enemies(&level);
while (solved == 0 && GameInfo -> collision != 1) {
printGameInfo(GameInfo);
noecho();
char move = getch();
echo();
if (GameInfo -> collision != 1) {
if (checkMoveValidity(move, GameInfo) == 1) {
solved = movePlayer(move, GameInfo);
if (solved == 1) {
break;
}
}
} else {
break;
}
}
if (solved == 1) {
pthread_cancel(enemies_th);
GameInfo->level++;
gameLevel(GameInfo);
} else {
// game over
pthread_cancel(enemies_th);
return;
}
}
Now, the code is much more complicated than here, but I think that shouldn't have any influence on this (?) as it executes properly, until the return statement. There is also ncurses and multithreading, quite complex custom structures, but it all works, up until that point. Any ideas ?
Tried putting print statements after each segment of code, everything worked up until this.
pthread_cancel() doesn't terminate the requested thread immediately. The only way to know that a cancelled thread has terminated is to call pthread_join(). If the thread is left running, it will interfere with use of the GameInfo variable in the next level of the game if the current level is solved, or may use the GameInfo variable beyond its lifetime if the current level was not solved and the main thread returns back to the main() function.
To make sure the old enemies thread has terminated, add calls to pthread_join() to the gameLevel() function as shown below:
if (solved == 1) {
pthread_cancel(enemies_th);
pthread_join(enemies_th);
GameInfo->level++;
gameLevel(GameInfo);
} else {
// game over
pthread_cancel(enemies_th);
pthread_join(enemies_th);
return;
}
The use of tail recursion in gameLevel() seems unnecessary. I recommend returning the solved value and letting the game() function start the next level:
In game():
while (gameLevel(&GameInfo)) {
GameInfo.level++;
}
In gameLevel():
int gameLevel(game_t *GameInfo) {
/* ... */
pthread_cancel(enemies_th);
pthread_join(enemies_th);
return solved;
}

C clock program

I was trying to create a clock program with c using the eclipse ide.
When I run the program it keeps executing every single count.
I used system("cls"). Also tried "clear"
It shows no error but it is not working. I want the screen cleared after every count. It is showing a ⍰ symbol sometimes.
https://i.stack.imgur.com/0ElDL.png ---This is what I got.
int main(void)
{
int hour,minute,second;
hour=minute=second=0;
setbuf(stdout,NULL);
while(1)
{
system("cls");
printf("%02d:%02d:%02d\n",hour,minute,second);
fflush(stdout);
second++;
if(second==60)
{
minute += 1;
second=0;
}
if(minute==60)
{
hour += 1;
minute=0;
}
if(hour==24)
{
hour=0;
minute=0;
second=0;
}
sleep(1);
}
return 0;
.
try using system("clear");
According to example published above you need only one line to display clock. It's easier to add carriage return:
while(1)
{
printf("%02d:%02d:%02d\r",hour,minute,second);
fflush(stdout);
...
}

Keeping track of all threads in a thread pool

I am looking at using the Windows Threading API and the issue it seems to have is you cannot keep track of when all the threads are completed. You can keep track of when the work item has been completed, assuming you kept track of each one. From my research there is no direct way to query the thread pool to see if the work items submitted has all be completed.
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
VOID CALLBACK MyWorkCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WORK Work) {
DWORD threadId = GetCurrentThreadId();
BOOL bRet = FALSE;
printf("%d thread\n", threadId);
return;
}
int main() {
TP_CALLBACK_ENVIRON CallBackEnviron;
PTP_POOL pool = NULL;
PTP_CLEANUP_GROUP cleanupgroup = NULL;
PTP_WORK_CALLBACK workcallback = MyWorkCallback;
PTP_TIMER timer = NULL;
PTP_WORK work = NULL;
InitializeThreadpoolEnvironment(&CallBackEnviron);
pool = CreateThreadpool(NULL);
SetThreadpoolThreadMaximum(pool, 1);
SetThreadpoolThreadMinimum(pool, 3);
SetThreadpoolCallbackPool(&CallBackEnviron, pool);
for (int i = 0; i < 10; ++i) {
work = CreateThreadpoolWork(workcallback, NULL, &CallBackEnviron);
SubmitThreadpoolWork(work);
WaitForThreadpoolWorkCallbacks(work, FALSE); // This waits for the work item to get completed.
}
return 1;
}
Here is a simple example. What happens is on the WaitForThreadpoolWorkCallbacks I am able to wait on that specific work item. Which is no problem if I am doing a few things. However, if I am traversing a directory and have thousands of files that I need to have work done on them, I don't want to keep track of each individual work item. Is it possible to query the Thread Pool queue to see if anything is left for processing? Or to find out if any of the threads are still working?
you need keep track of active tasks ( like pendcnt in comment) +1. but this must not be global variable, but member in some struct. and pass pointer to this struct to work item. increment this counter before call SubmitThreadpoolWork and decrement from callback, before exit. but you also need and event - set this event in signal state, when counter became 0. and wait on event from main thread. if your code inside dll, which can be unloaded - you need also reference dll, before SubmitThreadpoolWork and FreeLibraryWhenCallbackReturns from callback. also important that counter value - was 1 (not 0) ininitally - so this is count_of_active_cb + 1, and decrement it before begin wait (if not do this - counter can became 0 early - for instance first callback exit before you activate second)
class Task
{
HANDLE _hEvent = 0;
ULONG _dwThreadId = 0;
LONG _dwRefCount = 1;
public:
~Task()
{
if (_hEvent) CloseHandle(_hEvent);
}
ULONG Init()
{
if (HANDLE hEvent = CreateEvent(0, 0, 0, 0))
{
_hEvent = hEvent;
return NOERROR;
}
return GetLastError();
}
void AddTask()
{
InterlockedIncrementNoFence(&_dwRefCount);
}
void EndTask()
{
if (!InterlockedDecrement(&_dwRefCount))
{
if (_dwThreadId != GetCurrentThreadId())
{
if (!SetEvent(_hEvent)) __debugbreak();
}
}
}
void Wait()
{
_dwThreadId = GetCurrentThreadId();
EndTask();
if (_dwRefCount && WaitForSingleObject(_hEvent, INFINITE) != WAIT_OBJECT_0) __debugbreak();
}
};
VOID CALLBACK MyWorkCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WORK /*Work*/)
{
// need only if your code in dll which can be unloaded
FreeLibraryWhenCallbackReturns(Instance, (HMODULE)&__ImageBase);
WCHAR sz[32];
swprintf_s(sz, _countof(sz), L"[%x] thread", GetCurrentThreadId());
MessageBoxW(0, 0, sz, MB_ICONINFORMATION);
reinterpret_cast<Task*>(Parameter)->EndTask();
}
void CbDemo()
{
Task task;
if (task.Init() == NOERROR)
{
ULONG n = 2;
do
{
if (PTP_WORK pwk = CreateThreadpoolWork(MyWorkCallback, &task, 0))
{
HMODULE hmod;
// need only if your code in dll which can be unloaded
if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (PWSTR)&__ImageBase, &hmod))
{
task.AddTask();
SubmitThreadpoolWork(pwk);
}
CloseThreadpoolWork(pwk);
}
} while (--n);
MessageBoxW(0, 0, L"Main Thread", MB_ICONWARNING);
task.Wait();
__nop();
}
}

Priority Queue synchronization with pthreads

I'm working on a college assignment where we are to implement parallelized A* search for a 15 puzzle. For this part, we are to use only one priority queue (I suppose to see that the contention by multiple threads would limit speedup). A problem I am facing is properly synchronizing popping the next "candidate" from the priority queue.
I tried the following:
while(1) {
// The board I'm trying to pop.
Board current_board;
pthread_mutex_lock(&priority_queue_lock);
// If the heap is empty, wait till another thread adds new candidates.
if (pq->heap_size == 0)
{
printf("Waiting...\n");
pthread_mutex_unlock(&priority_queue_lock);
continue;
}
current_board = top(pq);
pthread_mutex_unlock(&priority_queue_lock);
// Generate the new boards from the current one and add to the heap...
}
I've tried different variants of the same idea, but for some reason there are occasions where the threads get stuck on "Waiting". The code works fine serially (or with two threads), so that leads me to believe this is the offending part of the code. I can post the entire thing if necessary. I feel like it's an issue with my understanding of the mutex lock though. Thanks in advance for help.
Edit:
I've added the full code for the parallel thread below:
// h and p are global pointers initialized in main()
void* parallelThread(void* arg)
{
int thread_id = (int)(long long)(arg);
while(1)
{
Board current_board;
pthread_mutex_lock(&priority_queue_lock);
current_board = top(p);
pthread_mutex_unlock(&priority_queue_lock);
// Move blank up.
if (current_board.blank_x > 0)
{
int newpos = current_board.blank_x - 1;
Board new_board = current_board;
new_board.board[current_board.blank_x][current_board.blank_y] = new_board.board[newpos][current_board.blank_y];
new_board.board[newpos][current_board.blank_y] = BLANK;
new_board.blank_x = newpos;
new_board.goodness = get_goodness(new_board.board);
new_board.turncount++;
if (check_solved(new_board))
{
printf("Solved in %d turns",new_board.turncount);
exit(0);
}
if (!exists(h,new_board))
{
insert(h,new_board);
push(p,new_board);
}
}
// Move blank down.
if (current_board.blank_x < 3)
{
int newpos = current_board.blank_x + 1;
Board new_board = current_board;
new_board.board[current_board.blank_x][current_board.blank_y] = new_board.board[newpos][current_board.blank_y];
new_board.board[newpos][current_board.blank_y] = BLANK;
new_board.blank_x = newpos;
new_board.goodness = get_goodness(new_board.board);
new_board.turncount++;
if (check_solved(new_board))
{
printf("Solved in %d turns",new_board.turncount);
exit(0);
}
if (!exists(h,new_board))
{
insert(h,new_board);
push(p,new_board);
}
}
// Move blank right.
if (current_board.blank_y < 3)
{
int newpos = current_board.blank_y + 1;
Board new_board = current_board;
new_board.board[current_board.blank_x][current_board.blank_y] = new_board.board[current_board.blank_x][newpos];
new_board.board[current_board.blank_x][newpos] = BLANK;
new_board.blank_y = newpos;
new_board.goodness = get_goodness(new_board.board);
new_board.turncount++;
if (check_solved(new_board))
{
printf("Solved in %d turns",new_board.turncount);
exit(0);
}
if (!exists(h,new_board))
{
insert(h,new_board);
push(p,new_board);
}
}
// Move blank left.
if (current_board.blank_y > 0)
{
int newpos = current_board.blank_y - 1;
Board new_board = current_board;
new_board.board[current_board.blank_x][current_board.blank_y] = new_board.board[current_board.blank_x][newpos];
new_board.board[current_board.blank_x][newpos] = BLANK;
new_board.blank_y = newpos;
new_board.goodness = get_goodness(new_board.board);
new_board.turncount++;
if (check_solved(new_board))
{
printf("Solved in %d turns",new_board.turncount);
exit(0);
}
if (!exists(h,new_board))
{
insert(h,new_board);
push(p,new_board);
}
}
}
return NULL;
}
I tried the following:
I don't see anything wrong with the code that follows, assuming that top also removes the board from the queue. It's wasteful (if the queue is empty, it will spin locking and unlocking the mutex), but not wrong.
I've added the full code
This is useless without the code for exists, insert and push.
One general observation:
pthread_mutex_lock(&priority_queue_lock);
current_board = top(p);
pthread_mutex_unlock(&priority_queue_lock);
In the code above, your locking is "ouside" of the top function. But here:
if (!exists(h,new_board))
{
insert(h,new_board);
push(p,new_board);
}
you either do no locking at all (in which case that's a bug), or you do locking "inside" exists, insert and push.
You should not mix "inside" and "outside" locking. Pick one or the other and stick with it.
If you in fact do not lock the queue inside exists, insert, etc. then you have a data race and are thinking of mutexes incorrectly: they protect invariants, and you can't check whether the queue is empty in parallel with another thread executing "remove top element" -- these operations require serialization, and thus must both be done under a lock.

Print data just once

i need to make somekind of "on-off" button with my project.
when the button not pressed, it supposed to print
stopped
if pressed
started
the problem is, when im not pressin it, it keep printin 'stopped', same when i keep pushin the button. i want it to only print the data once.
more detail, what i need is, the button hold the stay in 'STARTED' position until i press it again.
here is my code
{
int main (void)
int TestM4;
while(1)
{
if (!(PORTJ_IN&PIN1_bm)) //test m4
{
testM4 = 1;
printf("%d\n", testM4);
}
else
{
testM4 = 0;
printf("%d\n", testM4);
}
while(1)
This runs the while loop continuously.
So, it checks the buttons, prints out the statements, and then goes back straightaway to check them again.
To run it only once, remove the while loop altogether, but then the program will end pretty quickly.
Perhaps, look at ways to pause the program.
I don't know all the code, so while(1) could be good or bad code, but you can test as a flag to change it and print once only.
while(1)
{
if (!(PORTJ_IN&PIN1_bm)) //test m4
{
if(testM4 != 1) // status as button up
{
testM4 = 1;
printf("%d\n", testM4);
}
}
else
{
if(testM4 != 0)
{
testM4 = 0;
printf("%d\n", testM4);
}
}
}

Resources