Skip to content

Xnextevent Non Blocking Assignment

Hi!

The following code snippet is not blocking where it should! Please take a look...

struct timespec tv; //used to manage update intervals

while(1)
{
printf("\nLoop"); //this is where is actually blocks!! Strange.
//if any input event occured while the process was blocked for time

'updateInterval' microseconds, retrive & process it
if(XCheckWindowEvent(this->display, this->window, ExposureMask |

ButtonPressMask, &anEvent))
{
printf("\nGot an event");
switch(anEvent.type)
{
case Expose:
{
//code to be added later
break;
}
case ButtonPress:
{
if(anEvent.xbutton.button == Button3)
{
XCloseDisplay(this->display);
printf("\nClosed X server connection.\n\n");
this->cleanUpBodies(); //delete all bodies
return (1); //successful

completion of simulation
}
}
default: break;
}//end of event switch
}

//now draw the simulation window to depict updated state.
this->updateSimulationScreen(DRAW);
printf("\nDraw");

//wait for a time of 'updateInterval' microseconds
tv.tv_sec = 0;
tv.tv_usec = updateInterval;
select(0, NULL, NULL, NULL, &tv); //this is where it should

block
printf("\nSelect");

//erase current simulation screen
this->updateSimulationScreen(ERASE);
printf("\nErase");
//update state of all 'bodies'
this->updateState();
printf("\nUpdate State");
}

The Idea is, in the while loop, the code begins by checking is a mouse 3rd button click

event has occured or no. If yes, quit. Else, draw something to the window (

updateSimulationScreen(DRAW)), and block for 'updateInterval' microseconds. For blocking, i

have used select(). This is where the programme should block. After 'updateInterval'

microseconds, whatever was drawn to window previously should be erased (

updateSimulationScreen(ERASE)), and a call should be made updateState(). This updateState()

tells what's new to be drawn (doesn't actually draw).
Repeat loop.

The problem is that programme blocks at beginning of while loop, after executing printf("

\nLoop");
Not immediately after call to select()!!!
So there's no gap between calls to updateSimulationScreen(DRAW) and updateSimulationScreen(

ERASE), resulting in blank screen!!

Instead of select(), i tried using sleep() and nanosleep(). But the problem remains!

Please help.

Following is other relevant code:

void nature::updateSimulationScreen(enum UPDATE_MODE action)
//! Draws/erases all 'bodies' to/from the simulation

window and returns.
/*! Each 'body' is represented by a circle in the

simulation window.
* If 'action' is DRAW, all bodies contained in

'bodyList' are drawn to simulation window.
* This is done by drawing the 'bodies' using

foreground colour.
*
* If 'action' is ERASE, all bodies contained in

'bodyList' are erased from simulation window.
* This is done by drawing the 'bodies' using

background colour.
*/
{
if(action == ERASE)
{
//make background and foreground colours same
XSetForeground(this->display, this->gc, this->whitePixelID);
}

//for every 'body' in 'bodyList', compute x and y pixel coordinates, from it's x and

y distance coordinates in metres
dllNodeRef temp = this->bodyList;
body* bodyPtr;
while(temp != NULL)
{
bodyPtr = (body*)(temp->data);
double bodyX = bodyPtr->getXPosition();
double bodyY = bodyPtr->getYPosition();

//bodyX and bodyY are in metres, convert them to pixels, using conversion

scale 'yPixelScale'
//use (defaultScreenWidth / defaultScreenHeight) as aspect ratio of

simulation window
double screenX = bodyX/(this->yPixelScale * windowWidth / windowHeight);
double screenY = bodyY/this->yPixelScale;

if ( screenX < (-1*windowWidth/2 - RADIUS) || screenX > (windowWidth/2) \
|| screenY < (-1*windowHeight/2 - RADIUS) || screenY > (

windowHeight/2) )
//if the body lies outside drawable area, then no need to draw/erase it!
{
temp = temp->next;
}
else
{
this->translateCoordinates(&screenX, &screenY);
XDrawArc(this->display, this->window, this->gc, (int)screenX -

RADIUS, (int)screenY - RADIUS, RADIUS, RADIUS, 0, 360*60);
temp = temp->next;
}
}

if(action == ERASE)
{
//set foreground colour back to black
XSetForeground(this->display, this->gc, this->blackPixelID);
}
XFlush(this->display);
}

Sample output:

kapil@linux:~/Kopera/n-body-simulation> ./test

Loop <--output pauses after printing this!
Draw <--not after printing this!!
Select
Erase
Update State
Loop
Draw
Select
Erase
Update State
.
.
.
Loop
Draw
Select
Erase
Update State
Loop
Got an event
Closed X server connection.


Simulation finished alrite!kapil@linux:~/Kopera/n-body-simulation>


I also tried with checking return value of select, gives no errors. And also tried

XInternalConnectionNumbers() to get the internal file descriptor for connection with X

Server. This returns zero descriptors!! :-(

Regards,
Kapil

Blocking vs. Nonblocking in Verilog

The concept of Blocking vs. Nonblocking signal assignments is a unique one to hardware description languages. The main reason to use either Blocking or Nonblocking assignments is to generate either combinational or sequential logic. In software, all assignments work one at a time. So for example in the C code below:

LED_on = 0; count = count + 1; LED_on = 1;

The second line is only allowed to be executed once the first line is complete. Although you probably didn't know it, this is an example of a blocking assignment. One assignment blocks the next from executing until it is done. In a hardware description language such as Verilog there is logic that can execute concurrently or at the same time as opposed to one-line-at-a-time and there needs to be a way to tell which logic is which.

<=     Nonblocking Assignment

=      Blocking Assignment   


always @(posedge i_clock) begin r_Test_1 <= 1'b1; r_Test_2 <= r_Test_1; r_Test_3 <= r_Test_2; end

The always block in the Verilog code above uses the Nonblocking Assignment, which means that it will take 3 clock cycles for the value 1 to propagate from r_Test_1 to r_Test_3. Now consider this code:

always @(posedge i_clock) begin r_Test_1 = 1'b1; r_Test_2 = r_Test_1; r_Test_3 = r_Test_2; end

See the difference? In the always block above, the Blocking Assignment is used. In this example, the value 1 will immediately propagate to r_Test_3. The Blocking assignment immediately takes the value in the right-hand-side and assigns it to the left hand side. Here's a good rule of thumb for Verilog:

In Verilog, if you want to create sequential logic use a clocked always block with Nonblocking assignments. If you want to create combinational logic use an always block with Blocking assignments. Try not to mix the two in the same always block.

Nonblocking and Blocking Assignments can be mixed in the same always block. However you must be careful when doing this! It's actually up to the synthesis tools to determine whether a blocking assignment within a clocked always block will infer a Flip-Flop or not. If it is possible that the signal will be read before being assigned, the tools will infer sequential logic. If not, then the tools will generate combinational logic. For this reason it's best just to separate your combinational and sequential code as much as possible.

One last point: you should also understand the semantics of Verilog. When talking about Blocking and Nonblocking Assignments we are referring to Assignments that are exclusively used in Procedures (always, initial, task, function). You are only allowed to assign the reg data type in procedures. This is different from a Continuous Assignment. Continuous Assignments are everything that's not a Procedure, and only allow for updating the wire data type.