首页 > 代码库 > SDL线程使用

SDL线程使用

1、SDL_CreateThread
原始定义
  1. /**
  2. * Create a thread.
  3. */
  4. extern DECLSPEC SDL_Thread *SDLCALL
  5. SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
  6. pfnSDL_CurrentBeginThread pfnBeginThread,
  7. pfnSDL_CurrentEndThread pfnEndThread);

ID参数说明
1SDL_ThreadFunction fn线程所调用的函数
2const char *name 线程的名称
3void *data 线程所传入的数据
4pfnSDL_CurrentBeginThread pfnBeginThread 开始线程
5pfnSDL_CurrentEndThread pfnEndThread 结束线程
    

扩展定义
  1. /**
  2. * Create a thread.
  3. */
  4. #if defined(SDL_CreateThread) && SDL_DYNAMIC_API
  5. #undef SDL_CreateThread
  6. #define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
  7. #else
  8. #define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
  9. #endif
  10. #else
  11. /**
  12. * Create a thread.
  13. *
  14. * Thread naming is a little complicated: Most systems have very small
  15. * limits for the string length (Haiku has 32 bytes, Linux currently has 16,
  16. * Visual C++ 6.0 has nine!), and possibly other arbitrary rules. You‘ll
  17. * have to see what happens with your system‘s debugger. The name should be
  18. * UTF-8 (but using the naming limits of C identifiers is a better bet).
  19. * There are no requirements for thread naming conventions, so long as the
  20. * string is null-terminated UTF-8, but these guidelines are helpful in
  21. * choosing a name:
  22. *
  23. * http://stackoverflow.com/questions/149932/naming-conventions-for-threads
  24. *
  25. * If a system imposes requirements, SDL will try to munge the string for
  26. * it (truncate, etc), but the original string contents will be available
  27. * from SDL_GetThreadName().
  28. */
  29. extern DECLSPEC SDL_Thread *SDLCALL
  30. SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data);
  31. #endif
由定义可知在扩展定义中参数仅有三个比标准定义要少两。
在其宏定义中可以发现扩展定义中直接将参数后两项定义为NULL

ID参数说明
1SDL_ThreadFunction fn线程所调用的函数
2 const char *name线程的名称
3 void *data线程所传入的数据

2、SDL_Delay
原始定义
  1. /**
  2. * \brief Wait a specified number of milliseconds before returning.
  3. */
  4. extern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms);

本质上说,这个函数类似与Windows多线程中的Sleep
ID参数说明
1Uint32 ms
已毫秒为单位的数值

3、SDL_WaitThread
原始定义
  1. /**
  2. * Wait for a thread to finish. Threads that haven‘t been detached will
  3. * remain (as a "zombie") until this function cleans them up. Not doing so
  4. * is a resource leak.
  5. *
  6. * Once a thread has been cleaned up through this function, the SDL_Thread
  7. * that references it becomes invalid and should not be referenced again.
  8. * As such, only one thread may call SDL_WaitThread() on another.
  9. *
  10. * The return code for the thread function is placed in the area
  11. * pointed to by \c status, if \c status is not NULL.
  12. *
  13. * You may not wait on a thread that has been used in a call to
  14. * SDL_DetachThread(). Use either that function or this one, but not
  15. * both, or behavior is undefined.
  16. *
  17. * It is safe to pass NULL to this function; it is a no-op.
  18. */
  19. extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status);
等待这个线程直至它完成。


ID参数说明
1SDL_Thread * thread
所等待的线程
2int *status
返回的线程状态

4、SDL_WaitEvent
原始定义
  1. /**
  2. * \brief Waits indefinitely for the next available event.
  3. *
  4. * \return 1, or 0 if there was an error while waiting for events.
  5. *
  6. * \param event If not NULL, the next event is removed from the queue and
  7. * stored in that area.
  8. */
  9. extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * event);


ID参数说明
1int返回参数 返回0或1,如果返回错误将继续等下一个事件
2SDL_Event * event
返回SDL_EVENT事件

5、SDL_Event
原始定义
  1. /**
  2. * \brief General event structure
  3. */
  4. typedef union SDL_Event
  5. {
  6. Uint32 type; /**< Event type, shared with all events */
  7. SDL_CommonEvent common; /**< Common event data */
  8. SDL_WindowEvent window; /**< Window event data */
  9. SDL_KeyboardEvent key; /**< Keyboard event data */
  10. SDL_TextEditingEvent edit; /**< Text editing event data */
  11. SDL_TextInputEvent text; /**< Text input event data */
  12. SDL_MouseMotionEvent motion; /**< Mouse motion event data */
  13. SDL_MouseButtonEvent button; /**< Mouse button event data */
  14. SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */
  15. SDL_JoyAxisEvent jaxis; /**< Joystick axis event data */
  16. SDL_JoyBallEvent jball; /**< Joystick ball event data */
  17. SDL_JoyHatEvent jhat; /**< Joystick hat event data */
  18. SDL_JoyButtonEvent jbutton; /**< Joystick button event data */
  19. SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */
  20. SDL_ControllerAxisEvent caxis; /**< Game Controller axis event data */
  21. SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */
  22. SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */
  23. SDL_AudioDeviceEvent adevice; /**< Audio device event data */
  24. SDL_QuitEvent quit; /**< Quit request event data */
  25. SDL_UserEvent user; /**< Custom event data */
  26. SDL_SysWMEvent syswm; /**< System dependent window event data */
  27. SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
  28. SDL_MultiGestureEvent mgesture; /**< Gesture event data */
  29. SDL_DollarGestureEvent dgesture; /**< Gesture event data */
  30. SDL_DropEvent drop; /**< Drag and drop event data */
  31. /* This is necessary for ABI compatibility between Visual C++ and GCC
  32. Visual C++ will respect the push pack pragma and use 52 bytes for
  33. this structure, and GCC will use the alignment of the largest datatype
  34. within the union, which is 8 bytes.
  35. So... we‘ll add padding to force the size to be 56 bytes for both.
  36. */
  37. Uint8 padding[56];
  38. } SDL_Event;

6、SDL线程互斥的实现

SDL_mutex
互斥结构体
  1. /* The SDL mutex structure, defined in SDL_sysmutex.c */
  2. struct SDL_mutex;
  3. typedef struct SDL_mutex SDL_mutex;

SDL_CreateMutex
创建一个互斥对象,并初始化为解锁状态
  1. /**
  2. * Create a mutex, initialized unlocked.
  3. */
  4. extern DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void);

加互斥锁有两种
SDL_LockMutexSDL_TryLockMutex
SDL_LockMutex仅返回0和-1,SDL_TryLockMutex还会返回SDL_TIMEDOUT
  1. /**
  2. * Lock the mutex.
  3. *
  4. * \return 0, or -1 on error.
  5. */
  6. #define SDL_mutexP(m) SDL_LockMutex(m)
  7. extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex);
  8. /**
  9. * Try to lock the mutex
  10. *
  11. * \return 0, SDL_MUTEX_TIMEDOUT, or -1 on error
  12. */
  13. extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex);

解互斥锁函数
  1. /**
  2. * Unlock the mutex.
  3. *
  4. * \return 0, or -1 on error.
  5. *
  6. * \warning It is an error to unlock a mutex that has not been locked by
  7. * the current thread, and doing so results in undefined behavior.
  8. */
  9. #define SDL_mutexV(m) SDL_UnlockMutex(m)
  10. extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex);

释放锁资源
  1. /**
  2. * Destroy a mutex.
  3. */
  4. extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex * mutex);

条件变量
  1. /* The SDL condition variable structure, defined in SDL_syscond.c */
  2. struct SDL_cond;
  3. typedef struct SDL_cond SDL_cond;

 创建条件变量
  1. /**
  2. * Create a condition variable.
  3. *
  4. * Typical use of condition variables:
  5. *
  6. * Thread A:
  7. * SDL_LockMutex(lock);
  8. * while ( ! condition ) {
  9. * SDL_CondWait(cond, lock);
  10. * }
  11. * SDL_UnlockMutex(lock);
  12. *
  13. * Thread B:
  14. * SDL_LockMutex(lock);
  15. * ...
  16. * condition = true;
  17. * ...
  18. * SDL_CondSignal(cond);
  19. * SDL_UnlockMutex(lock);
  20. *
  21. * There is some discussion whether to signal the condition variable
  22. * with the mutex locked or not. There is some potential performance
  23. * benefit to unlocking first on some platforms, but there are some
  24. * potential race conditions depending on how your code is structured.
  25. *
  26. * In general it‘s safer to signal the condition variable while the
  27. * mutex is locked.
  28. */
  29. extern DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void);
通过条件变量的变化来改变互斥锁的状态。


销毁条件变量
  1. /**
  2. * Destroy a condition variable.
  3. */
  4. extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond * cond);


重启一个正在等待条件变量的线程
  1. /**
  2. * Restart one of the threads that are waiting on the condition variable.
  3. *
  4. * \return 0 or -1 on error.
  5. */
  6. extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond * cond);

重启所有正在等待条件变量的线程
  1. /**
  2. * Restart all threads that are waiting on the condition variable.
  3. *
  4. * \return 0 or -1 on error.
  5. */
  6. extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond * cond);

 条件变量等待
  1. /**
  2. * Wait on the condition variable, unlocking the provided mutex.
  3. *
  4. * \warning The mutex must be locked before entering this function!
  5. *
  6. * The mutex is re-locked once the condition variable is signaled.
  7. *
  8. * \return 0 when it is signaled, or -1 on error.
  9. */
  10. extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex);

ID参数说明
1SDL_cond * cond
条件变量
2SDL_mutex * mutex
SDL互斥对象

  1. /**
  2. * Waits for at most \c ms milliseconds, and returns 0 if the condition
  3. * variable is signaled, ::SDL_MUTEX_TIMEDOUT if the condition is not
  4. * signaled in the allotted time, and -1 on error.
  5. *
  6. * \warning On some platforms this function is implemented by looping with a
  7. * delay of 1 ms, and so should be avoided if possible.
  8. */
  9. extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond * cond,
  10. SDL_mutex * mutex, Uint32 ms);
注:如果超时将发送SDL_TIMEDOUT的超时信号,如果 未发送该信号,那么将返回-1
ID参数说明
1SDL_cond * cond
条件变量
2SDL_mutex * mutex
SDL互斥对象
3Uint32 ms
超时时间,单位毫秒


代码实例:
  1. // SDL_ThreadTest.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #define __STDC_CONSTANT_MACROS
  5. #define SDL_MAIN_HANDLED
  6. #define SDL_THREAD_FINISH (SDL_USEREVENT+1)
  7. // 导入SDL库
  8. #include "SDL.h"
  9. int i = 0;
  10. SDL_mutex* data_lock;
  11. SDL_cond * cond;
  12. SDL_Thread* pthread1;
  13. SDL_Thread* pthread2;
  14. SDL_Event event;
  15. int SDLThread1(void *data)
  16. {
  17. int * pi = (int*)data;
  18. for (;;)
  19. {
  20. if ((*pi) > 99)
  21. {
  22. SDL_Event event;
  23. event.type = SDL_THREAD_FINISH;
  24. SDL_PushEvent(&event);
  25. break;
  26. }
  27. SDL_LockMutex(data_lock);
  28. (*pi)++;
  29. printf("This is SDL Thread1, Current i is [%d]\n", (*pi));
  30. if ((*pi)==50)
  31. {
  32. SDL_CondSignal(cond);
  33. }
  34. SDL_UnlockMutex(data_lock);
  35. SDL_Delay(10);
  36. }
  37. return 0;
  38. }
  39. int SDLThread2(void *data)
  40. {
  41. int * pi = (int*)data;
  42. for (;;)
  43. {
  44. if ((*pi) > 99)
  45. {
  46. SDL_Event event;
  47. event.type = SDL_THREAD_FINISH;
  48. SDL_PushEvent(&event);
  49. break;
  50. }
  51. SDL_LockMutex(data_lock);
  52. SDL_CondWait(cond, data_lock);
  53. (*pi)++;
  54. printf("This is SDL Thread2, Current i is [%d]\n", (*pi));
  55. SDL_UnlockMutex(data_lock);
  56. SDL_Delay(10);
  57. }
  58. return 0;
  59. }
  60. int main()
  61. {
  62. SDL_Init(SDL_INIT_EVERYTHING);
  63. data_lock = SDL_CreateMutex();
  64. cond = SDL_CreateCond();
  65. pthread1 = SDL_CreateThread(SDLThread1, "Thread1", &i);
  66. pthread2 = SDL_CreateThread(SDLThread2, "Thread2", &i);
  67. for (;;)
  68. {
  69. SDL_WaitEvent(&event);
  70. if (event.type == SDL_THREAD_FINISH)
  71. break;
  72. }
  73. SDL_DestroyCond(cond);
  74. SDL_DestroyMutex(data_lock);
  75. SDL_Quit();
  76. system("pause");
  77. return 0;
  78. }

两个线程操作int i。创建互斥锁data_lock在各线程的操作段锁定i。
然后通过 SDL_cond条件变量设定仅在i值为50时解锁第二个线程。
同时使用自定义SDL_EVENT 来结束整个程序。

实际输出结果如下:
技术分享
 










来自为知笔记(Wiz)


SDL线程使用