What to use for Networking?

Hi,

I am making a game engine and I am going to use SDL because it had cross
platform and some other features…

But what would you suggest to use for Game Networking?

Thanks,
Andrew

SDL_Net is what i use…

it does TCP/IP, UDP and even does broadcasting!> ----- Original Message -----

From: computernerd8888@cox.net (Andrew Balmos)
To:
Sent: Saturday, September 20, 2003 9:48 PM
Subject: [SDL] What to use for Networking?

Hi,

I am making a game engine and I am going to use SDL because it had cross
platform and some other features…

But what would you suggest to use for Game Networking?

Thanks,
Andrew


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Hi,

I am making a game engine and I am going to use SDL because it had cross
platform and some other features…

But what would you suggest to use for Game Networking?

Net2, what else? :slight_smile: http://gameprogrammer.com/game.html it is based
entirely on the SDL_net and so is as cross platform as SDL.

BTW, I’m very biased on this subject.

	Bob PendletonOn Sat, 2003-09-20 at 23:48, Andrew Balmos wrote:

Thanks,
Andrew


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±----------------------------------+

Hey Bob,

I was wondering what advantages Net2 has over SDL_Net? Your comments make
me wonder if i should switch.

Thanks!
Atrix> ----- Original Message -----

From: bob@pendleton.com (Bob Pendleton)
To: “SDL Mailing List”
Sent: Monday, September 22, 2003 2:20 PM
Subject: Re: [SDL] What to use for Networking?

On Sat, 2003-09-20 at 23:48, Andrew Balmos wrote:

Hi,

I am making a game engine and I am going to use SDL because it had cross
platform and some other features…

But what would you suggest to use for Game Networking?

Net2, what else? :slight_smile: http://gameprogrammer.com/game.html it is based
entirely on the SDL_net and so is as cross platform as SDL.

BTW, I’m very biased on this subject.

Bob Pendleton

Thanks,
Andrew


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±----------------------------------+


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Thanks!

Andrew
Church Punks! Truth Rebellion! Audio A!> ----- Original Message -----

From: bob@pendleton.com (Bob Pendleton)
Newsgroups: gmane.comp.lib.sdl
Sent: Monday, September 22, 2003 2:20 PM
Subject: Re: What to use for Networking?

On Sat, 2003-09-20 at 23:48, Andrew Balmos wrote:

Hi,

I am making a game engine and I am going to use SDL because it had cross
platform and some other features…

But what would you suggest to use for Game Networking?

Net2, what else? :slight_smile: http://gameprogrammer.com/game.html it is based
entirely on the SDL_net and so is as cross platform as SDL.

BTW, I’m very biased on this subject.

Bob Pendleton

Thanks,
Andrew


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±----------------------------------+

Hey Bob,

I was wondering what advantages Net2 has over SDL_Net? Your comments make
me wonder if i should switch.

There are several advantages. Net2 runs the networking code in a
separate thread so that you do not have to poll for network traffic. It
reports all incoming traffic using events. You get the events and
process them in your main event thread just like you process mouse
events or keyboard events. It has greatly simplified functions for
creating sockets and accepting connections. Not to mention simplified
APIs for sending and receiving UDP messages. And, it enforces strict
length controls on messages. So, the code should be free of buffer over
run attacks.

Net2 does require you to use the fastevents library. That library speeds
up event processing in SDL and provides a thread safe interface between
the main SDL thread and the Net2 thread.

Net2 does not work on OSes that do not support threads.

I know it is being used on projects on both Linux and Windows. The
interesting thing is that I developed it on Linux. When someone ported
it to Windows they found only one thing that had to be changed to get it
to compile and work there.

Take a look at the documentation and the sample programs. Most people
like what they see.
http://gameprogrammer.com/game.html

		Bob PendletonOn Mon, 2003-09-22 at 16:39, Alan Wolfe wrote:

Thanks!
Atrix

----- Original Message -----
From: “Bob Pendleton” <@Bob_Pendleton>
To: “SDL Mailing List”
Sent: Monday, September 22, 2003 2:20 PM
Subject: Re: [SDL] What to use for Networking?

On Sat, 2003-09-20 at 23:48, Andrew Balmos wrote:

Hi,

I am making a game engine and I am going to use SDL because it had cross
platform and some other features…

But what would you suggest to use for Game Networking?

Net2, what else? :slight_smile: http://gameprogrammer.com/game.html it is based
entirely on the SDL_net and so is as cross platform as SDL.

BTW, I’m very biased on this subject.

Bob Pendleton

Thanks,
Andrew


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±----------------------------------+


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±----------------------------------+

I just downloaded the FastEvent library from his website because I too think in events :slight_smile:
The library is such a huge improvement in both speed and processor utilization.
Kudos to Bob on a job well done!

With that said, I need to make a couple of comments and suggestions since I plan on incorporating the fast event code into a project I’m working on.

Firstly, Win32 and older mac users cannot make use of the SDL_INIT_EVENTTHREAD flag when calling SDL_Init(). Using this flag causes the application to fail when running under those two environments. Hopefully, somebody can better explain to me why that is and maybe add it to the docs? :slight_smile: It took me a bit to trace into the SDL library to figure that out. Thus the fast event example code may want to account for that.

Second, there are a few small bugs that were relatively easy to fix:

The while loop in the existing version of FE_PushEvent() never ends.
The SDL_PushEvent() call will return either 0 if success or -1 if unable
to add the event or error.
Thus the change needed is
from
while (0 >= SDL_PushEvent(ev))
to
while (0 != SDL_PushEvent(ev))

The code examples thread1.c, thread2.c, and thread3.c should also be modified similarly.

In FE_WaitEvent(), there is a call to SDL_PollEvent(). This causes a very subtle change in expected library behavior when compared to SDL_WaitEvent(). In SDL_WaitEvent, a failure is returned as 0, and a sucess returns a 1. By calling SDL_PollEvent inside FE_WaitEvent there is no way to account for the two possibles errors, thus “potentially” causing an app to hang.

My suggestion is to replace the call to SDL_PollEvent inside FE_WaitEvent with a call to SDL_PeepEvents and mimic the behavior of SDL_WaitEvent.

With those issues out of the way, I agree with Bob’s statement regarding the need to have SDL handle the allocation of subtypes of an SDL_UserEvent, especially as SDL grows in size with library writers add additional capabilities. The lack of this feature could indeed cause issues in the future. See Bob’s Net2 project for that discussion.

Finally, as a suggestion, perhaps the god’s of SDL may offer inter-thread communication via SDL events? Using the same portable thread, event, and network code on both the client and server makes a coder happy. :smiley:

Thanks for listening ;)---------------------------------
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software

I just downloaded the FastEvent library from his website because I too
think in events :slight_smile:
The library is such a huge improvement in both speed and processor
utilization.
Kudos to Bob on a job well done!

Thank You.

With that said, I need to make a couple of comments and suggestions
since I plan on incorporating the fast event code into a project I’m
working on.

Firstly, Win32 and older mac users cannot make use of the
SDL_INIT_EVENTTHREAD flag when calling SDL_Init(). Using this flag
causes the application to fail when running under those two
environments. Hopefully, somebody can better explain to me why that
is and maybe add it to the docs? :slight_smile: It took me a bit to trace into
the SDL library to figure that out. Thus the fast event example code
may want to account for that.

This is a judgement call. I only work on Linux these days, so I can’t
test on Windows. I do not want to post code that I have not tested. But,
point taken, I have added comments about the problems with
SDL_INIT_EVENTTHREAD and the lack of thread support on older versions of
MacOS to the documentation.

Second, there are a few small bugs that were relatively easy to fix:

Note that none of these were bugs when the library was written. Up until
1.2.5 (IIRC) the documented behavior of PushEvent() was different from
the actual behavior. Rather than fix the documentation the SDL
maintainers decided to fix the code causing an incompatibility between
the latest versions of SDL and all previous versions. The result is that
the code you have is correct for many versions of SDL installed on
peoples computers. But, not correct for people using the current version
of the libraries.

I think it has been long enough so I have posted new versions of the
code on my web site.

The while loop in the existing version of FE_PushEvent() never ends.
The SDL_PushEvent() call will return either 0 if success or -1 if
unable
to add the event or error.
Thus the change needed is
from
while (0 >= SDL_PushEvent(ev))
to
while (0 != SDL_PushEvent(ev))

The code examples thread1.c, thread2.c, and thread3.c should also be
modified similarly.

In FE_WaitEvent(), there is a call to SDL_PollEvent(). This causes a
very subtle change in expected library behavior when compared to
SDL_WaitEvent(). In SDL_WaitEvent, a failure is returned as 0, and a
sucess returns a 1. By calling SDL_PollEvent inside FE_WaitEvent
there is no way to account for the two possibles errors, thus
"potentially" causing an app to hang.

Interesting point. I see where you are coming from on this, but you need
to take a look at the code for the SDL functions to see what is going
on. SDL_PollEvent() calls SDL_PeepEvent() and as far as I can tell my
function has the same semantics as the SDL functions.

My suggestion is to replace the call to SDL_PollEvent inside
FE_WaitEvent with a call to SDL_PeepEvents and mimic the behavior of
SDL_WaitEvent.

After looking at the SDL code please let me know if you still see a
problem.

With those issues out of the way, I agree with Bob’s statement
regarding the need to have SDL handle the allocation of subtypes of an
SDL_UserEvent, especially as SDL grows in size with library writers
add additional capabilities. The lack of this feature could indeed
cause issues in the future. See Bob’s Net2 project for that
discussion.

We had a long discussion about that on this list. No solution was
proposed that makes everyone happy. People want to be able to use a
switch statement to handle events which implies a static declaration of
event types.

Finally, as a suggestion, perhaps the god’s of SDL may offer
inter-thread communication via SDL events? Using the same portable
thread, event, and network code on both the client and server makes a
coder happy. :smiley:

Just use fastevents. It works.

Thanks for listening :wink:


Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software

	Bob PendletonOn Wed, 2003-09-24 at 07:13, Rob Neff wrote:


±----------------------------------+

#Firstly, Win32 and older mac users cannot make use of the SDL_INIT_EVENTTHREAD flag when calling SDL_Init(). Using this flag causes the application to fail when running under those two environments. Hopefully, somebody can better explain to me why that is and maybe add it to the docs? :slight_smile: It took me a bit to trace into the SDL library to figure that out. Thus the fast event example code may want to account for that.

From what Bob told me when I asked him about it, it is not strictly
necessery to use SDL_INIT_EVENTTHREAD in order to use Net2, but there
might have been some performance issue involved here. Maybe he could
answer it once more…

I would also ask the documenters of SDL to document this feature; when
I had problem with Net2 and tried to figure out what
SDL_INIT_EVENTTHREAD actually meant, the SDL-doc didn’t help me at
all…

/Olof

Bob,

After looking at the SDL code please let me know if you still see a
problem.

My original observation was based from the code contained in SDL_Events.c.
The concern is how would an app that’s calling FE_WaitEvent() know that an error occured inside SDL? For example, a -1 return from SDL_PeepEvents() indicates either the event system is uninitialized/unloaded or there was a weird mutex error. An application would never receive that error because FE_WaitEvent() would never come out of the while loop. Thus, to the developer it would appear as a hung app. FE_PushEvent() suffers the same issue. By replacing SDL_PollEvent with SDL_PeepEvent() the calling app can now check for this condition.

An added bonus is that by replacing the calls to SDL_PollEvent with SDL_PeepEvents we gain more speed by not having to make superflous calls. :slight_smile:

The following optimized functions with same SDL behavior now look like:

int FE_PushEvent(SDL_Event *event)
{
int val;

SDL_LockMutex(eventLock);
while ( 0 == ( val = SDL_PeepEvents ( event, 1, SDL_ADDEVENT, 0 ) ) )
SDL_CondWait ( eventWait, eventLock );
SDL_UnlockMutex ( eventLock );

if ( val > 0 )
SDL_CondSignal ( eventWait );

return ( val < 0 ? -1 : 0 );
}

int FE_PollEvent(SDL_Event *event)
{
int val;

SDL_LockMutex ( eventLock );
SDL_PumpEvents();
val = SDL_PeepEvents ( event, 1, SDL_GETEVENT, SDL_ALLEVENTS );
SDL_UnlockMutex ( eventLock );

if ( val > 0 )
SDL_CondSignal( eventWait );

/* We can’t return -1, just return 0 (no event) on error */
return ( val <= 0 ? 0 : 1 );
}

int FE_WaitEvent ( SDL_Event *event )
{
int val;

SDL_LockMutex ( eventLock );
SDL_PumpEvents();
while ( 0 == ( val = SDL_PeepEvents ( event, 1, SDL_GETEVENT, SDL_ALLEVENTS ) ) )
SDL_CondWait ( eventWait, eventLock );
SDL_UnlockMutex ( eventLock );
SDL_CondSignal ( eventWait );

return ( val < 0 ? 0 : 1 );
}

We had a long discussion about that on this list. No solution was
proposed that makes everyone happy. People want to be able to use a
switch statement to handle events which implies a static declaration of
event types.

hmmmmm…I can see both sides of that coin.

Finally, as a suggestion, perhaps the god’s of SDL may offer
inter-thread communication via SDL events? Using the same portable
thread, event, and network code on both the client and server makes a
coder happy. :smiley:

Just use fastevents. It works.

Actually, what I was thinking here was main thread to worker thread communication via SDL events. Wishful thinking, huh? :)---------------------------------
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software

Bob,

After looking at the SDL code please let me know if you still see a
problem.

My original observation was based from the code contained in
SDL_Events.c.
The concern is how would an app that’s calling FE_WaitEvent() know
that an error occured inside SDL? For example, a -1 return from
SDL_PeepEvents() indicates either the event system is
uninitialized/unloaded or there was a weird mutex error. An
application would never receive that error because FE_WaitEvent()
would never come out of the while loop. Thus, to the developer it
would appear as a hung app. FE_PushEvent() suffers the same issue.
By replacing SDL_PollEvent with SDL_PeepEvent() the calling app can
now check for this condition.

Take another look at the SDL code. I don’t see anyway for the error to
be propagated up to the program from SDL_WaitEvent() or from
SDL_PollEvent() the error is converted to 0 or just causes the function
to loop.

An added bonus is that by replacing the calls to SDL_PollEvent with
SDL_PeepEvents we gain more speed by not having to make superflous
calls. :slight_smile:

There are no superfluous calls that I can see. I think you missed the
existence of the timer in the fast events code.

The following optimized functions with same SDL behavior now look
like:

int FE_PushEvent(SDL_Event *event)
{
int val;

SDL_LockMutex(eventLock);
while ( 0 == ( val = SDL_PeepEvents ( event, 1, SDL_ADDEVENT, 0 ) )
)
SDL_CondWait ( eventWait, eventLock );
SDL_UnlockMutex ( eventLock );

if ( val > 0 )
SDL_CondSignal ( eventWait );

return ( val < 0 ? -1 : 0 );
}

int FE_PollEvent(SDL_Event *event)
{
int val;

SDL_LockMutex ( eventLock );
SDL_PumpEvents();
val = SDL_PeepEvents ( event, 1, SDL_GETEVENT, SDL_ALLEVENTS );
SDL_UnlockMutex ( eventLock );

if ( val > 0 )
SDL_CondSignal( eventWait );

/* We can’t return -1, just return 0 (no event) on error */
return ( val <= 0 ? 0 : 1 );
}

int FE_WaitEvent ( SDL_Event *event )
{
int val;

SDL_LockMutex ( eventLock );
SDL_PumpEvents();
while ( 0 == ( val = SDL_PeepEvents ( event, 1, SDL_GETEVENT,
SDL_ALLEVENTS ) ) )
SDL_CondWait ( eventWait, eventLock );
SDL_UnlockMutex ( eventLock );
SDL_CondSignal ( eventWait );

return ( val < 0 ? 0 : 1 );
}

You are missing the effect of the timer. Your version of the functions
only pump events once. That means that if there are no pending SDL
events they hang until net2 sends them an event and signals the
condition. The SDL events won’t be pumped and checked again until the
next call to waitevent. The result is that even if the program doesn’t
hang the net2 events are received out of order with SDL events.

I do it the way I do it so that pump events gets called every 10
milliseconds as the result of the timer firing. That is the same thing
that SDL does, it just does it by use of a delay(10) which is one of the
reasons why I wrote the library in the first place.

We had a long discussion about that on this list. No solution was
proposed that makes everyone happy. People want to be able to use a
switch statement to handle events which implies a static declaration
of
event types.

hmmmmm…I can see both sides of that coin.

Finally, as a suggestion, perhaps the god’s of SDL may offer
inter-thread communication via SDL events? Using the same portable
thread, event, and network code on both the client and server makes
a

coder happy. :smiley:

Just use fastevents. It works.

Actually, what I was thinking here was main thread to worker thread
communication via SDL events. Wishful thinking, huh? :slight_smile:

Oh, I see what you mean. Just use semaphore controlled queues like
everyone else. They work. They are simple. And, they are well
documented. It would be very easy to build an API that looks a lot like
fast events that used such a mechanism to communicate between threads.

	Bob PendletonOn Wed, 2003-09-24 at 15:55, Rob Neff wrote:

Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software

±----------------------------------+

Bob,

Take another look at the SDL code. I don’t see anyway for the error to
be propagated up to the program from SDL_WaitEvent() or from
SDL_PollEvent() the error is converted to 0 or just causes the function
to loop.

As currently coded in 1.2.6, an application programmer cannot use SDL_PollEvent (or even SDL_PushEvent!) to detect the presence of an error. However, the function
SDL_WaitEvent returns 0 to indicate the presence of an error. FE_WaitEvent, as currently written, silently eats that error code/condition and thus modifys
expected library behavior.

To see this, modify the SDL library function SDL_PeepEvents to always return -1 and
recompile the library. Now use the fast event thread4.c example code to run against this modification. FE_WaitEvent will hang indefinately. Yes, this is a contrived example, but it shows the difference of behavior between SDL_WaitEvent and FE_WaitEvent. Using
SDL_WaitEvent, the application programmer is at least afforded the opportunity
to bail out, writing to an error log then gracefully exiting, or whatever.

The one library behavior modification I WOULD like to see is for FE_PushEvent to return an error code (which is what my modified version of FE_PushEvent does). Now, I’m not 100% certain what every OS does with a failed mutex lock (mutex code inside
SDL_PeepEvents). Will locking attempts, once failed, always failed? Or are they a “retry” operation. I’m aware of a thread being placed in an “on-hold” status while waiting
for a lock operation to complete, but if that lock attempt fails, will it also fail on each subsequent call afterwards? That’s why I believe Fast Events should return the failure status to the application programmer and let him/her decide, as follows:

int FE_PushEvent(SDL_Event *event)
{
int val;
SDL_LockMutex ( eventLock );
while ( 0 == ( val = SDL_PeepEvents ( event, 1, SDL_ADDEVENT, 0 ) ) )
SDL_CondWait ( eventWait, eventLock );
SDL_UnlockMutex ( eventLock );
if ( val > 0 )
SDL_CondSignal ( eventWait );
return ( val < 0 ? -1 : 0 );
}

An added bonus is that by replacing the calls to SDL_PollEvent with
SDL_PeepEvents we gain more speed by not having to make superflous
calls. :slight_smile:

There are no superfluous calls that I can see. I think you missed the
existence of the timer in the fast events code.

The superflous call is the call to the wrapper functions SDL_WaitEvent, SDL_PushEvent, and SDL_PollEvent, which all call SDL_PeepEvents. By calling SDL_PeepEvents directly from the FastEvent functions, you elimate the “superflous” calls to the wrapper functions, thus avoiding the addition stack pushes/pops and calls. Of course, you must also mimic the behavior of the wrapper functions themselves, something I’ve taken care of in my modifications to the FE functions.

Also, as you may have noticed, the conditional checks are compared against the value 0 (zero) as opposed to a -1. The assembly/object code generated results in shorter/faster instructions when using zero as the test value as opposed to some other value. This decreases object code size and increases the speed of the function. Note: although I’m rather familiar with Intel CPU assembly code, I’m “assuming” this is also true of other CPU architectures.

You are missing the effect of the timer. Your version of the functions
only pump events once. That means that if there are no pending SDL
events they hang until net2 sends them an event and signals the
condition. The SDL events won’t be pumped and checked again until the
next call to waitevent. The result is that even if the program doesn’t
hang the net2 events are received out of order with SDL events.

I do it the way I do it so that pump events gets called every 10
milliseconds as the result of the timer firing. That is the same thing
that SDL does, it just does it by use of a delay(10) which is one of the
reasons why I wrote the library in the first place.

You are absolutely correct. I missed that completely inside FE_WaitEvent while loop as I was more trying to show the difference in library behavior between SDL_WaitEvent and FE_WaitEvent. The other functions, as previously written, do in fact function properly
with respect to emulation of the existing SDL function behavior. The correct modification to FE_WaitEvent would look like:

int FE_WaitEvent(SDL_Event *event)
{
int val;
SDL_LockMutex ( eventLock );
SDL_PumpEvents();
while (0 == (val = SDL_PeepEvents( event, 1, SDL_GETEVENT, SDL_ALLEVENTS )))
{
SDL_CondWait ( eventWait, eventLock );
SDL_PumpEvents();
}
SDL_UnlockMutex ( eventLock );
SDL_CondSignal ( eventWait );
return (val < 0 ? 0 : 1);
}

Actually, what I was thinking here was main thread to worker thread
communication via SDL events. Wishful thinking, huh? :slight_smile:
Oh, I see what you mean. Just use semaphore controlled queues like
everyone else. They work. They are simple. And, they are well
documented. It would be very easy to build an API that looks a lot like
fast events that used such a mechanism to communicate between threads.

That’s kind of where I’m going. It would be nice to be able to have one library that does this for you, is portable across multiple platforms, and integrates easily within SDL (or the FastEvent) library. Care to join forces and tackle this? :)---------------------------------
Do you Yahoo!?
The New Yahoo! Shopping - with improved product search

Debugging multi-threaded applications is hard. Unit testing a library sub-system should help ensure an application developer using said library that s/he is coding using a bullet-proof system, especially when that library is an integral piece to a larger library.

Realizing that some previous pieces of code were not, in fact, bullet-proof (well, as bullet-proof as code can potentially be) corrections were necessary ( sigh ).
Let he who is without sin cast the first stone! :slight_smile:

Rather than assuming that all mutex and condition operations are successful, the return values from these functions are checked for errors as well. The only function not being evaluated is the mutex unlock function as the next call to any of the FE functions will indicate the error condition. If the SDL developer list can bear with me for just one
more iteration… :slight_smile:

int FE_PushEvent(SDL_Event *event)
{
int val;

if ( ( val = SDL_LockMutex ( eventLock ) ) == 0)
{
while ( 0 == ( val = SDL_PeepEvents ( event, 1, SDL_ADDEVENT, 0 ) ) )
if ( ( val = SDL_CondWait ( eventWait, eventLock ) ) < 0 )
break;
SDL_UnlockMutex ( eventLock );

if ( val > 0 )
{
    if ( SDL_CondSignal ( eventWait ) < 0 )
      val = -1;
}

}
return ( val < 0 ? -1 : 0 );
}

int FE_PollEvent(SDL_Event *event)
{
int val;

if ( ( val = SDL_LockMutex ( eventLock ) ) == 0 )
{
SDL_PumpEvents();
val = SDL_PeepEvents ( event, 1, SDL_GETEVENT, SDL_ALLEVENTS );
SDL_UnlockMutex ( eventLock );

if ( val > 0 )
{
    if ( SDL_CondSignal ( eventWait ) < 0 )
      val = -1;
}

}

/* We can’t return -1, just return 0 (no event) on error */
return (val <= 0 ? 0 : 1);
}

int FE_WaitEvent(SDL_Event *event)
{
int val;

if ( ( val = SDL_LockMutex ( eventLock ) ) == 0 )
{
SDL_PumpEvents();
while (0 == (val = SDL_PeepEvents ( event, 1, SDL_GETEVENT, SDL_ALLEVENTS )))
{
if ( ( val = SDL_CondWait ( eventWait, eventLock ) ) < 0 )
break;
SDL_PumpEvents();
}
SDL_UnlockMutex ( eventLock );

if ( val > 0 )
{
    if ( SDL_CondSignal ( eventWait ) < 0 )
      val = -1;
}

}

return (val < 0 ? 0 : 1);
}

It also dawned on me that there were two different functions required to obtain error codes: FE_GetError() for the FE_Init() function, and SDL_GetError() for the rest of the FE functions. I felt that, as a library to be integrated within SDL as a drop-in replacement for the SDL event functions, that these functions should also set the SDL error and eliminate the function FE_GetError() (and the internal setError() function) completely.

In my eye this makes for a more seamless integration and feel references to FE_GetError and setError should be removed. Errors occuring within FE_Init should set the SDL error code (using SDL_SetError ) which the calling application can check for with SDL_GetError. As a matter of fact, all errors occuring within any FE function can be obtained this way now using SDL_GetError. The check for a failed timer subsystem initialization is also watched for now.
FE_Init() and quit could now looks like:

int FE_Init(void)
{
int val = -1;

if (0 == (SDL_INIT_TIMER & SDL_WasInit(SDL_INIT_TIMER)))
{
if ( SDL_InitSubSystem(SDL_INIT_TIMER) < 0 )
return -1;
}
if ( ( eventLock = SDL_CreateMutex() ) == NULL )
{
SDL_SetError(“FE: can’t create a mutex”);
}
else if ( ( eventWait = SDL_CreateCond() ) == NULL )
{
SDL_SetError(“FE: can’t create a condition variable”);
}
else if ( ( eventTimer = SDL_AddTimer( 10, timerCallback, NULL ) ) == NULL )
{
SDL_SetError(“FE: can’t add a timer”);
}
else
{
val = 0;
}

if ( val != 0 )
FE_Quit();

return val;
}

void FE_Quit(void)
{
if ( eventLock != NULL )
{
SDL_DestroyMutex ( eventLock );
eventLock = NULL;
}

if ( eventWait != NULL )
{
SDL_DestroyCond ( eventWait );
eventWait = NULL;
}

if ( eventTimer != NULL )
{
SDL_RemoveTimer ( eventTimer );
eventTimer = NULL;
}
}

It is my sincere hope that someone, somewhere, can make use of
the efforts of both Bob Pendleton’s orginal design and coding
and my modifications to it. Thanks again for listening…---------------------------------
Do you Yahoo!?
The New Yahoo! Shopping - with improved product search

Bob,

Take another look at the SDL code. I don’t see anyway for the error
to
be propagated up to the program from SDL_WaitEvent() or from
SDL_PollEvent() the error is converted to 0 or just causes the
function
to loop.

As currently coded in 1.2.6, an application programmer cannot use
SDL_PollEvent (or even SDL_PushEvent!) to detect the presence of an
error. However, the function
SDL_WaitEvent returns 0 to indicate the presence of an error.
FE_WaitEvent, as currently written, silently eats that error
code/condition and thus modifys
expected library behavior.

Point taken, but I don’t know that I want to fix this. I’m not sure it
is an error. The slight difference in semantics isn’t enough of a
problem for me to be very upset about it. Basically, you can only get
that error if you have forgotten to initialize the event system or have
serious memory corruption.

Does anyone else see this as a problem? Feel free to chime in folks. It
has taken me longer to read this email than it would take to rewrite the
function.

To see this, modify the SDL library function SDL_PeepEvents to always
return -1 and
recompile the library. Now use the fast event thread4.c example code
to run against this modification. FE_WaitEvent will hang
indefinately. Yes, this is a contrived example, but it shows the
difference of behavior between SDL_WaitEvent and FE_WaitEvent. Using
SDL_WaitEvent, the application programmer is at least afforded the
opportunity
to bail out, writing to an error log then gracefully exiting, or
whatever.

The one library behavior modification I WOULD like to see is for
FE_PushEvent to return an error code (which is what my modified
version of FE_PushEvent does). Now, I’m not 100% certain what every
OS does with a failed mutex lock (mutex code inside
SDL_PeepEvents).

Basically, if you were able to allocate the mutex the operations on it
are going to work. If it fails it generally means your code is suffering
from serious memory corruption and there isn’t much you can do about it.

Will locking attempts, once failed, always failed? Or are they a
"retry" operation. I’m aware of a thread being placed in an "on-hold"
status while waiting
for a lock operation to complete, but if that lock attempt fails, will
it also fail on each subsequent call afterwards? That’s why I believe
Fast Events should return the failure status to the application
programmer and let him/her decide, as follows:

int FE_PushEvent(SDL_Event *event)
{
int val;
SDL_LockMutex ( eventLock );
while ( 0 == ( val = SDL_PeepEvents ( event, 1, SDL_ADDEVENT, 0 ) )
)
SDL_CondWait ( eventWait, eventLock );
SDL_UnlockMutex ( eventLock );
if ( val > 0 )
SDL_CondSignal ( eventWait );
return ( val < 0 ? -1 : 0 );
}

An added bonus is that by replacing the calls to SDL_PollEvent with
SDL_PeepEvents we gain more speed by not having to make superflous
calls. :slight_smile:

There are no superfluous calls that I can see. I think you missed
the
existence of the timer in the fast events code.

The superflous call is the call to the wrapper functions
SDL_WaitEvent, SDL_PushEvent, and SDL_PollEvent, which all call
SDL_PeepEvents. By calling SDL_PeepEvents directly from the FastEvent
functions, you elimate the “superflous” calls to the wrapper
functions, thus avoiding the addition stack pushes/pops and calls. Of
course, you must also mimic the behavior of the wrapper functions
themselves, something I’ve taken care of in my modifications to the FE
functions.

I’ve seen this discussion too many time to take is seriously anymore.
The overhead of making these function calls is not large enough to worry
about.

OTOH, if you really care about the nanoseconds “wasted” here you need to
consider the HUGE assumption that you are making. You assume that the
implementation of the SDL functions will stay the same so that it is
safe to reimplement them in my code. My code assumes that the interface
will stay the same but the implementation may change. I prefer my way of
doing things to your way of doing things.

Also, as you may have noticed, the conditional checks are compared
against the value 0 (zero) as opposed to a -1. The assembly/object
code generated results in shorter/faster instructions when using zero
as the test value as opposed to some other value. This decreases
object code size and increases the speed of the function. Note:
although I’m rather familiar with Intel CPU assembly code, I’m
"assuming" this is also true of other CPU architectures.

You are missing the effect of the timer. Your version of the
functions
only pump events once. That means that if there are no pending SDL
events they hang until net2 sends them an event and signals the
condition. The SDL events won’t be pumped and checked again until
the
next call to waitevent. The result is that even if the program
doesn’t
hang the net2 events are received out of order with SDL events.

I do it the way I do it so that pump events gets called every 10
milliseconds as the result of the timer firing. That is the same
thing
that SDL does, it just does it by use of a delay(10) which is one of
the
reasons why I wrote the library in the first place.

You are absolutely correct. I missed that completely inside
FE_WaitEvent while loop as I was more trying to show the difference in
library behavior between SDL_WaitEvent and FE_WaitEvent. The other
functions, as previously written, do in fact function properly
with respect to emulation of the existing SDL function behavior. The
correct modification to FE_WaitEvent would look like:

int FE_WaitEvent(SDL_Event *event)
{
int val;
SDL_LockMutex ( eventLock );
SDL_PumpEvents();
while (0 == (val = SDL_PeepEvents( event, 1, SDL_GETEVENT,
SDL_ALLEVENTS )))
{
SDL_CondWait ( eventWait, eventLock );
SDL_PumpEvents();
}
SDL_UnlockMutex ( eventLock );
SDL_CondSignal ( eventWait );
return (val < 0 ? 0 : 1);
}

Actually, what I was thinking here was main thread to worker thread
communication via SDL events. Wishful thinking, huh? :slight_smile:
Oh, I see what you mean. Just use semaphore controlled queues like
everyone else. They work. They are simple. And, they are well
documented. It would be very easy to build an API that looks a lot
like
fast events that used such a mechanism to communicate between
threads.

That’s kind of where I’m going. It would be nice to be able to have
one library that does this for you, is portable across multiple
platforms, and integrates easily within SDL (or the FastEvent)
library. Care to join forces and tackle this? :slight_smile:

No, not really. This is code you can look up in any basic text on
threading. It is usually right there next to the description of a
semaphore. It is what the semaphore was invented for.

	Bob PendletonOn Fri, 2003-09-26 at 00:49, Rob Neff wrote:

Do you Yahoo!?
The New Yahoo! Shopping - with improved product search

±----------------------------------+