c - creating threads & joining them in a for loop - c

So basically I'm making a simulator in c for vehicles entering in and out of cell phone tower zones. I'm trying to add code in simulator.c that makes the function spawn a new thread for each cell tower as well as one thread to handle the display. The simulator program should continue up until all 7 cell tower threads have completed, and the cell tower threads should continue until they receive a shutdown request. The display thread runs indefinitely but gets killed when the simulator process completes. I'm having trouble understanding what parameters I'm supposed to use to create and join the threads. I posted below what I have so far in the simulator.c program. My attempt is trying to loop the statements to make 7 threads for 7 cell towers. I'm not sure if my first parameter for pthread_create is correct and I'm not really sure what my 4th parameter is supposed to be. I know I'm supposed to pass in some sort of argument but I'm not sure what. Also I'm not too sure what the requirements mean for "the cell tower threads should continue until they receive a shutdown request." Each cell tower thread is supposed to call handleIncomingRequests() from cellTower.c and the display thread should call showSimulation() from display.c
Any help would be really appreciated. I watched some videos online about threading in c but I'm still a little confused as to how they work. I posted below the files I felt were only related to this question, but if anyone wants me to post every file for this entire program I don't mind.
simulator.c:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "simulator.h"
#include "display.c"
#include "cellTower.c"
int main() {
City ottawa;
// Cell tower data
short xLocations[7] = {100, 400, 650, 640, 400, 120, 200};
short yLocations[7] = {100, 200, 150, 450, 500, 350, 500};
short cellRadii[7] = {110, 200, 150, 180, 160, 120, 100};
int cellColors[7] = {0xFF8822 /*Orange*/, 0xFF2222 /*Red*/, 0xFFFF44 /*Yellow*/,
0x22FF22 /*Green*/, 0xAA66FF /*Purple*/, 0x0099FF /*Blue*/,
0x999999 /*LightGray*/};
// Set up the Cell Towers with the above data ... and no connected vehicles to begin
ottawa.numTowers = 7;
for (int i=0; i<ottawa.numTowers; i++) {
ottawa.towers[i].online = 1;
ottawa.towers[i].id = (unsigned char)i;
ottawa.towers[i].x = xLocations[i];
ottawa.towers[i].y = yLocations[i];
ottawa.towers[i].radius = cellRadii[i];
ottawa.towers[i].color = cellColors[i];
ottawa.towers[i].numConnectedVehicles = 0;
for (int j=0; j<MAX_CONNECTIONS; j++)
ottawa.towers[i].connectedVehicles[j].connected = 0;
}
// Remove the line of code below. Add code to spawn the necessary threads and
// wait for their completion before exiting gracefully with some kind of message
pthread_t cellTowers[ottawa.numTowers];
int i;
for(i = 0; i < ottawa.numTowers; i++){
pthread_create(cellTowers[i], NULL, handleIncomingRequests, "");
pthread_join(cellTowers[i], NULL);
}
pthread_t displayTower;
pthread_create(&displayTower, NULL, showSimulation, "");
}
simulator.h:
#define VEHICLE_SPEED 3 // Forward pixels per movement
#define VEHICLE_TURN_ANGLE 5 // degrees to turn for each vehicle movement
#define NUM_TOWERS 7 // Number of cell towers within the city borders
#define SERVER_IP "127.0.0.1" // IP address of simulator server
#define SERVER_PORT 6000 // PORT of the simulator server
// Command codes sent from client to server
#define SHUTDOWN 1
#define CONNECT 2
#define UPDATE 3
// Command codes sent from server to client
#define YES 5
#define NO 6
#define NOT_OK_BOUNDARY 7
#define NOT_OK_COLLIDE 8
typedef struct {
int x;
int y;
int direction;
char towerID;
} Vehicle;
typedef struct {
int x;
int y;
char connected;
} ConnectedVehicle;
typedef struct {
char online; // 0 = no, 1 = yes
char id;
short x;
short y;
short radius;
int color;
ConnectedVehicle connectedVehicles[MAX_CONNECTIONS];
short numConnectedVehicles;
} CellTower;
typedef struct {
CellTower towers[NUM_TOWERS];
short numTowers;
} City;
cellTower.c:
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
void *handleIncomingRequests(void *ct) {
CellTower *tower = ct;
}
display.c:
#include <unistd.h>
#include <X11/Xlib.h>
//Display-related variables
Display *display;
Window win;
GC gc;
// Initialize and open the simulator window with size CITY_WIDTH x CITY_HEIGHT.
void initializeWindow() {
// Open connection to X server
display = XOpenDisplay(NULL);
// Create a simple window, set the title and get the graphics context then
// make is visible and get ready to draw
win = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
CITY_WIDTH, CITY_HEIGHT, 0, 0x000000, 0xFFFFFF);
XStoreName(display, win, "Vehicle Simulator");
gc = XCreateGC(display, win, 0, NULL);
XMapWindow(display, win);
XFlush(display);
usleep(20000); // sleep for 20 milliseconds.
}
// Close the display window
void closeWindow() {
XFreeGC(display, gc);
XUnmapWindow(display, win);
XDestroyWindow(display, win);
XCloseDisplay(display);
}
// Redraw all the cell towers and all the vehicles that are connected to towers.
// This code should run in an infinite loop continuously drawing the city.
// Vehicles are drawn as circles with radius VEHICLE_RADIUS.
void *showSimulation(void *c) {
City *city = c;
// Open the window
initializeWindow();
// Now keep redrawing until someone kills the thread
while(1) {
// Erase the background
XSetForeground(display, gc, 0xFFFFFF);
XFillRectangle(display, win, gc, 0, 0, CITY_WIDTH, CITY_HEIGHT);
// Draw all the cell towers
for (int i=0; i<city->numTowers; i++) {
short r = city->towers[i].radius;
XSetForeground(display, gc, city->towers[i].color);
for (int b=-3;b<=3; b++)
XDrawArc(display, win, gc,
city->towers[i].x-r+b, city->towers[i].y-r+b,
2*(r-b), 2*(r-b), 0, 360*64);
}
// Draw all the vehicles within each cell tower's range
for (int t=0; t<city->numTowers; t++) {
for (int i=0; i<MAX_CONNECTIONS; i++) {
if (city->towers[t].connectedVehicles[i].connected) {
XSetForeground(display, gc, city->towers[t].color);
XFillArc(display, win, gc,
city->towers[t].connectedVehicles[i].x-VEHICLE_RADIUS,
city->towers[t].connectedVehicles[i].y-VEHICLE_RADIUS,
2*VEHICLE_RADIUS, 2*VEHICLE_RADIUS, 0, 360*64);
XSetForeground(display, gc, 0x000000); // draw a black border
XDrawArc(display, win, gc,
city->towers[t].connectedVehicles[i].x-VEHICLE_RADIUS,
city->towers[t].connectedVehicles[i].y-VEHICLE_RADIUS,
2*VEHICLE_RADIUS, 2*VEHICLE_RADIUS, 0, 360*64);
}
}
}
XFlush(display);
usleep(2000);
}
closeWindow();
pthread_exit(NULL);
}
Also if anyone has some useful resources for threading, that would also be appreciated!!!

There are a few problems here:
pthread_t cellTowers[ottawa.numTowers];
int i;
for(i = 0; i < ottawa.numTowers; i++){
pthread_create(cellTowers[i], NULL, handleIncomingRequests, "");
pthread_join(cellTowers[i], NULL);
}
pthread_create stores the thread-id that it creates in memory location pointed at by the first argument.
Therefore, the first argument should be &cellTowers[i] (or equivalently cellTowers + i), and not cellTowers[i] that you are passing.
Your compiler should warn you that you are passing in a value of the wrong type. If you have not turned on compiler warnings, do so now. For GCC, use -Wall -Wextra -Werror.
Whenever you observe this sequence:
pthread_create ...
pthread_join ...
with the same thread-id in both, you can immediately know that the program is broken. The pthread_join will wait for the thread to complete. Therefore, no additional threads will be created until the first thread exits.
The way most threaded programs work:
for (...) pthread_create... // create all worker threads
// possibly perform additional work in main thread
for (...) pthread_join... // wait for all threads to finish
Finally, getting to your question: what should the 4th parameter be?
Since handleIncomingRequests() expects the argument to be a pointer to CellTower, that's what the 4th argument should be (that argument is passed directly to your function).
In this program, the 4th argument should be &ottawa.towers[i] (or equivalently ottawa.towers + i).

Related

multithreading with mutexes in c and running one thread at a time

I have an array of 100 requests(integers). I want to create 4 threads to which i call a function(thread_function) and with this function i want every thread to take one by one the requests:
(thread0->request0,
thread1->request1,
thread2->request2,
thread3->request3
and then thread0->request4 etc up to 100) all these by using mutexes.
Here is the code i have writen so far:
threadRes = pthread_create(&(threadID[i]), NULL,thread_function, (void *)id_size);
This is inside my main and it is in a loop for 4 times.Now outside my main:
void *thread_function(void *arg){
int *val_p=(int *) arg;
for(i=0; i<200; i=i+2)
{
f=false;
for (j= 0; j<100; j++)
{
if (val_p[i]==cache[j].id)
f=true;
}
if(f==true)
{
printf("The request %d has been served.\n",val_p[i]);
}
else
{
cache[k].id=val_p[i];
printf("\nCurrent request to be served:%d \n",cache[k].id);
k++;
}
}
Where: val_p is the array with the requests and cache is an array of structs to store the id(requests).
-So now i want mutexes to synchronize my threads. I considered using inside my main:
pthread_join(threadID[0], NULL);
pthread_join(threadID[1], NULL);
pthread_join(threadID[2], NULL);
pthread_join(threadID[3], NULL);
pthread_mutex_destroy(&mutex);
and inside the function to use:
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
Before i finish i would like to say that so far my programm result is that 4threads run 100 requests each(400) and what i want to achieve is that 4threads run 100 threads total.
Thanks for your time.
You need to use a loop that looks like this:
Acquire lock.
See if there's any work to be done. If not, release the lock and terminate.
Mark the work that we're going to do as not needing to be done anymore.
Release the lock.
Do the work.
(If necessary) Acquire the lock. Mark the work done and/or report results. Release the lock.
Go to step 1.
Notice how while holding the lock, the thread discovers what work it should do and then prevents any other thread from taking the same assignment before it releases the lock. Note also that the lock is not held while doing the work so that multiple threads can work concurrently.
You may want to post more of your code. How the arrays are set up, how the segment is passed to the individual threads, etc.
Note that using printf will perturb the timing of the threads. It does its own mutex for access to stdout, so it's probably better to no-op this. Or, have a set of per-thread logfiles so the printf calls don't block against one another.
Also, in your thread loop, once you set f to true, you can issue a break as there's no need to scan further.
val_p[i] is loop invariant, so we can fetch that just once at the start of the i loop.
We don't see k and cache, but you'd need to mutex wrap the code that sets these values.
But, that does not protect against races in the for loop. You'd have to wrap the fetch of cache[j].id in a mutex pair inside the loop. You might be okay without the mutex inside the loop on some arches that have good cache snooping (e.g. x86).
You might be better off using stdatomic.h primitives. Here's a version that illustrates that. It compiles but I've not tested it:
#include <stdio.h>
#include <pthread.h>
#include <stdatomic.h>
int k;
#define true 1
#define false 0
struct cache {
int id;
};
struct cache cache[100];
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
void *
thread_function(void *arg)
{
int *val_p = arg;
int i;
int j;
int cval;
int *cptr;
for (i = 0; i < 200; i += 2) {
int pval = val_p[i];
int f = false;
// decide if request has already been served
for (j = 0; j < 100; j++) {
cptr = &cache[j].id;
cval = atomic_load(cptr);
if (cval == pval) {
f = true;
break;
}
}
if (f == true) {
dbgprt("The request %d has been served.\n",pval);
continue;
}
// increment the global k value [atomically]
int kold = atomic_load(&k);
int knew;
while (1) {
knew = kold + 1;
if (atomic_compare_exchange_strong(&k,&kold,knew))
break;
}
// get current cache value
cptr = &cache[kold].id;
int oldval = atomic_load(cptr);
// mark the cache
// this should never loop because we atomically got our slot with
// the k value
while (1) {
if (atomic_compare_exchange_strong(cptr,&oldval,pval))
break;
}
dbgprt("\nCurrent request to be served:%d\n",pval);
}
return (void *) 0;
}

Is it possible to make a loading animation in a Console Application using C?

I would like to know if it is possible to make a loading animation in a Console Application that would always appear in the same line, like a flashing dot or a more complex ASCII animation.
Perhaps like this
#include <stdio.h>
#include <time.h>
#define INTERVAL (0.1 * CLOCKS_PER_SEC) // tenth second
int main(void) {
int i = 0;
clock_t target;
char spin[] = "\\|/-"; // '\' needs escape seq
printf(" ");
while(1) {
printf("\b%c", spin[i]);
fflush(stdout);
i = (i + 1) % 4;
target = clock() + (clock_t)INTERVAL;
while (clock() < target);
}
return 0;
}
The more portable way would be to use termcap/terminfo or (n)curses.
If you send ANSI escape sequences you assume the terminal to be capable of interpreting them (and if it isn't it'll result in a big mess.)
It's essentially a system that describes the capabilities of the terminal (if there's one connected at all).
In these days one tends to forget but the original tty didn't have a way to remove ink from the paper it typed the output on ...
Termcap tutorials are easy enough to find on Google. Just one in the GNU flavor here: https://www.gnu.org/software/termutils/manual/termcap-1.3/html_mono/termcap.html (old, but should still be good)
(n)curses is a library that will allow you control and build entire text based user interfaces if you want to.
Yes it is.
One line
At first if you want to make animation only at one line, you could use putchar('\b') to remove last character and putchar('\r') to return to line beginning and then rewrite it.
Example:
#include
#include
int main() {
int num;
while (1) {
for (num = 1; num <= 3; num++) {
putchar('.');
fflush(stdout);
sleep(1);
}
printf("\r \r"); // or printf("\b\b\b");
}
return 0;
}
But if you want to place it at specified line, you can clear and re-draw every frame, or use libs.
Clearing method
You can do this with system("clear") or with printf("\e[1;1H\e[2J").
After that you'll need to re-draw your frame. I don't recommend this method.
But this is really unportable.
Other libraries
You can use ncurses.h or conio.h depending on system type.
Ncurses example:
#include <stdio.h>
#include <unistd.h>
#include <ncurses.h>
int main() {
int row, col;
initscr();
getmaxyx(stdscr, row, col);
char loading[] = "-\\|/";
while (1) {
for (int i = 0; i < 8; i++) {
mvaddch(row/2, col/2, loading[i%4]);
refresh();
sleep(1);
mvaddch(row/2, col/2, '\b');
}
}
endwin();
return 0;
}

Audio samples producer multiple threads OSX

This question is a follow-up to a former question (Audio producer threads with OSX AudioComponent consumer thread and callback in C), including a test example, which works and behaves as expected but does not quite answer the question. I have substantially rephrased the question, and re-coded the example, so that it only contains plain-C code. (I've found out that few Objective-C portions of code in the former example only caused confusion and distracted the reader from what's essential in the question.)
In order to take advantage of multiple processor cores as well as to make the CoreAudio pull-model render thread as lightweight as possible, the LPCM samples' producer routine clearly has to "sit" on a different thread, outside the real-lime-priority render thread/callback. It must feed the samples to a circular buffer (TPCircularBuffer in this example), from which the system would schedule data pull-out in quants of inNumberFrames.
The Grand Central Dispatch API offers a simple solution, which I've deduced upon some individual research (including trial-and-error coding). This solution is elegant, since it doesn't block anything nor conflict between push and pull models. Yet the GCD, which is supposed to take care of "sub-threading" does not by far meet the specific parallelization requirements for the work threads of the producer code, so I had to explicitely spawn a number of POSIX threads, depending on the number of logical cores available. Although results are already remarkable in terms of speeding-up the computation I still feel a bit unconfortable mixing the POSIX and GCD. In particular it goes for the variable wait_interval, and computing it properly, not by predicting how many PCM samples may the render thread require for the next cycle.
Here's the shortened and simplified (pseudo)code for my test program, in plain-C.
Controller declaration:
#include "TPCircularBuffer.h"
#include <AudioToolbox/AudioToolbox.h>
#include <AudioUnit/AudioUnit.h>
#include <dispatch/dispatch.h>
#include <sys/sysctl.h>
#include <pthread.h>
typedef struct {
TPCircularBuffer buffer;
AudioComponentInstance toneUnit;
Float64 sampleRate;
AudioStreamBasicDescription streamFormat;
Float32* f; //array of updated frequencies
Float32* a; //array of updated amps
Float32* prevf; //array of prev. frequencies
Float32* preva; //array of prev. amps
Float32* val;
int* arg;
int* previous_arg;
UInt32 frames;
int state;
Boolean midif; //wip
} MyAudioController;
MyAudioController gen;
dispatch_semaphore_t mSemaphore;
Boolean multithreading, NF;
typedef struct data{
int tid;
int cpuCount;
}data;
Controller management:
void setup (void){
// Initialize circular buffer
TPCircularBufferInit(&(self->buffer), kBufferLength);
// Create the semaphore
mSemaphore = dispatch_semaphore_create(0);
// Setup audio
createToneUnit(&gen);
}
void dealloc (void) {
// Release buffer resources
TPCircularBufferCleanup(&buffer);
// Clean up semaphore
dispatch_release(mSemaphore);
// dispose of audio
if(gen.toneUnit){
AudioOutputUnitStop(gen.toneUnit);
AudioUnitUninitialize(gen.toneUnit);
AudioComponentInstanceDispose(gen.toneUnit);
}
}
Dispatcher call (launching producer queue from the main thread):
void dproducer (Boolean on, Boolean multithreading, Boolean NF)
{
if (on == true)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
if((multithreading)||(NF))
producerSum(on);
else
producer(on);
});
}
return;
}
Threadable producer routine:
void producerSum(Boolean on)
{
int rc;
int num = getCPUnum();
pthread_t threads[num];
data thread_args[num];
void* resulT;
static Float32 frames [FR_MAX];
Float32 wait_interval;
int bytesToCopy;
Float32 floatmax;
while(on){
wait_interval = FACT*(gen.frames)/(gen.sampleRate);
Float32 damp = 1./(Float32)(gen.frames);
bytesToCopy = gen.frames*sizeof(Float32);
memset(frames, 0, FR_MAX*sizeof(Float32));
availableBytes = 0;
fbuffW = (Float32**)calloc(num + 1, sizeof(Float32*));
for (int i=0; i<num; ++i)
{
fbuffW[i] = (Float32*)calloc(gen.frames, sizeof(Float32));
thread_args[i].tid = i;
thread_args[i].cpuCount = num;
rc = pthread_create(&threads[i], NULL, producerTN, (void *) &thread_args[i]);
}
for (int i=0; i<num; ++i) rc = pthread_join(threads[i], &resulT);
for(UInt32 samp = 0; samp < gen.frames; samp++)
for(int i = 0; i < num; i++)
frames[samp] += fbuffW[i][samp];
//code for managing producer state and GUI updates
{ ... }
float *head = TPCircularBufferHead(&(gen.buffer), &availableBytes);
memcpy(head,(const void*)frames,MIN(bytesToCopy, availableBytes));//copies frames to head
TPCircularBufferProduce(&(gen.buffer),MIN(bytesToCopy,availableBytes));
dispatch_semaphore_wait(mSemaphore, dispatch_time(DISPATCH_TIME_NOW, wait_interval * NSEC_PER_SEC));
if(gen.state == stopped){gen.state = idle; on = false;}
for(int i = 0; i <= num; i++)
free(fbuffW[i]);
free(fbuffW);
}
return;
}
A single producer thread may look somewhat like this:
void *producerT (void *TN)
{
Float32 samples[FR_MAX];
data threadData;
threadData = *((data *)TN);
int tid = threadData.tid;
int step = threadData.cpuCount;
int *ret = calloc(1,sizeof(int));
do_something(tid, step, &samples);
{ … }
return (void*)ret;
}
Here is the render callback (CoreAudio real-time consumer thread):
static OSStatus audioRenderCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
MyAudioController *THIS = (MyAudioController *)inRefCon;
// An event happens in the render thread- signal whoever is waiting
if (THIS->state == active) dispatch_semaphore_signal(mSemaphore);
// Mono audio rendering: we only need one target buffer
const int channel = 0;
Float32* targetBuffer = (Float32 *)ioData->mBuffers[channel].mData;
memset(targetBuffer,0,inNumberFrames*sizeof(Float32));
// Pull samples from circular buffer
int32_t availableBytes;
Float32 *buffer = TPCircularBufferTail(&THIS->buffer, &availableBytes);
//copy circularBuffer content to target buffer
int bytesToCopy = ioData->mBuffers[channel].mDataByteSize;
memcpy(targetBuffer, buffer, MIN(bytesToCopy, availableBytes));
{ … };
TPCircularBufferConsume(&THIS->buffer, availableBytes);
THIS->frames = inNumberFrames;
return noErr;
}
Grand Central Dispatch already takes care of dispatching operations to multiple processor cores and threads. In typical real-time audio rendering or processing, one never needs to wait on a signal or semaphore, as the circular buffer consumption rate is very predictable, and drifts extremely slowly over time. The AVAudioSession API (if available) and Audio Unit API and callback allow you to set and determine the callback buffer size, and thus the maximum rate at which the circular buffer can change. Thus you can dispatch all render operations on a timer, render the exact number needed per timer period, and let the buffer size and state compensate for any jitter in thread dispatch time.
In extremely long running audio renders, you might want to measure the drift between timer operations and real-time audio consumption (sample rate), and tweak the number of samples rendered or the timer offset.

How to pass a sequential counter by reference to pthread start routine?

Below is my C code to print an increasing global counter, one increment per thread.
#include <stdio.h>
#include <pthread.h>
static pthread_mutex_t pt_lock = PTHREAD_MUTEX_INITIALIZER;
int count = 0;
int *printnum(int *num) {
pthread_mutex_lock(&pt_lock);
printf("thread:%d ", *num);
pthread_mutex_unlock(&pt_lock);
return NULL;
}
int main() {
int i, *ret;
pthread_t pta[10];
for(i = 0; i < 10; i++) {
pthread_mutex_lock(&pt_lock);
count++;
pthread_mutex_unlock(&pt_lock);
pthread_create(&pta[i], NULL, (void *(*)(void *))printnum, &count);
}
for(i = 0; i < 10; i++) {
pthread_join(pta[i], (void **)&ret);
}
}
I want each thread to print one increment of the global counter but they miss increments and sometimes access same values of global counter from two threads. How can I make threads access the global counter sequentially?
Sample Output:
thread:2
thread:3
thread:5
thread:6
thread:7
thread:7
thread:8
thread:9
thread:10
thread:10
Edit
Blue Moon's answer solves this question. Alternative approach is available in MartinJames'es comment.
A simple-but-useless approach is to ensure thread1 prints 1, thread2 prints 2 and so on is to put join the thread immmediately:
pthread_create(&pta[i], NULL, printnum, &count);
pthread_join(pta[i], (void **)&ret);
But this totally defeats the purpose of multi-threading because only one can make any progress at a time.
Note that I removed the superfluous casts and also the thread function takes a void * argument.
A saner approach would be to pass the loop counter i by value so that each thread would print different value and you would see threading in action i.e. the numbers 1-10 could be printed in any order and also each thread would print a unique value.

C and xlib: Crash in XPending() in a very simple program

I'm a beginner with xlib. I tried to program an Xwindow application using select() based on this example: how to quit the blocking of xlib's XNextEvent.
But the code mentioned above crashes in the XPending function. So I tried to isolate the problem and on my system even this from my point of view very simple example crashes on line 28. Due to several tests I assume is crashes internally by calling XFlush(). At the line marked with "// <- CRASH" I think XPending should return 0. Is that correct?
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
Display *dis;
Window win;
int x11_fd;
fd_set in_fds;
struct timeval tv;
XKeyEvent ev;
int main() {
dis = XOpenDisplay(NULL);
win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 256, 256, \
0, BlackPixel (dis, 0), BlackPixel(dis, 0));
XSelectInput(dis, win,
KeyPressMask | KeyReleaseMask );
XMapWindow(dis, win);
XFlush(dis);
printf("Xpending: %d\n",XPending(dis));
printf("Xpending: %d\n",XPending(dis));
XPeekEvent(dis, (XEvent*) &ev);
printf("type: %d button: 0x%X state: 0x%x\n",ev.type, ev.keycode, ev.state);
int j = XPending(dis); // <- CRASH
printf("XPending: %d\n",j);
return 0;
}
Is this a bug or have I mistaken a major concept in xlib?
XKeyEvent is bigger in bytes than XEvent
when you receive a bigger event, the ev variable will overflow.
using malloc, you actualy get more bytes than you asked, solving the problem.
better solution will be using a XEvent ev;
XEvent ev;
...
XNextEvent( & ev );
...
printf( "%d\n", ev.xkey.keycode
);
I have solved the issue. Although I don't understand why it works:
Instead of using a global ev variable I declared it inside the main function body:
XKeyEvent *ev = (XKeyEvent*) malloc(sizeof(XKeyEvent));
and adapted its pointer nature to the program.

Resources