Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在多线程程序中,通过用户事件传递短数据的正确方法是什么?_C++_Multithreading_Events_Sdl - Fatal编程技术网

C++ 在多线程程序中,通过用户事件传递短数据的正确方法是什么?

C++ 在多线程程序中,通过用户事件传递短数据的正确方法是什么?,c++,multithreading,events,sdl,C++,Multithreading,Events,Sdl,在我基于SDL2的程序中,我有一个主线程处理事件队列,另一个线程定期将事件推送到事件队列 // thread #2 event.type = UserEventType; event.user.code = SomeCode; event.user.data = UInt8Value; SDL_PushEvent(&event); 主线程获取此事件,并提取数据 // main thread SDL_PollEvent(&event); /* ... */ Uint8 Uint8

在我基于SDL2的程序中,我有一个主线程处理事件队列,另一个线程定期将事件推送到事件队列

// thread #2
event.type = UserEventType;
event.user.code = SomeCode;
event.user.data = UInt8Value;
SDL_PushEvent(&event);
主线程获取此事件,并提取数据

// main thread
SDL_PollEvent(&event); /* ... */
Uint8 Uint8Value = event.user.data;
这个解决方案似乎不太好,因为Uint8和void*的大小不同,并且取决于平台。最安全的方法是在堆中分配Uint8值,并通过event.user.data传递指向它的指针,然后在主线程中释放内存。但是
当您只需要传递一个字节时,为每个事件分配/释放内存不是很高效吗?也许有一个更好的解决方案,它也是可移植的?

关于形成循环队列的事件容器呢?您可以加载下一个空闲元素,然后将其地址推送到队列中。然后,用户/主设备可以解除对其的锁定。这仍然是低效的,但至少可以避免新建/删除微小结构的痛苦。

这里有一种方法

//  All the possible character values
// Make this a global
char dummy_values[256];


// thread #2
event.type = UserEventType;
event.user.code = SomeCode;
event.user.data = dummy_values + UInt8Value;
SDL_PushEvent(&event);


// main thread
SDL_PollEvent(&event); /* ... */
Uint8 Uint8Value = static_cast<char*>(event.user.data) - dummy_values;
//所有可能的字符值
//让这成为一个全球性的问题
字符伪_值[256];
//螺纹#2
event.type=UserEventType;
event.user.code=SomeCode;
event.user.data=dummy_值+UInt8Value;
SDL_PushEvent(&event);
//主线
SDL_PollEvent(&event);/**/
Uint8 Uint8Value=静态\u转换(event.user.data)-虚拟\u值;

这是一个256字节数组的成本,但它避免了动态内存,并且应该是安全的和可移植的

这很痛苦,不是吗?将小数据项推到生产者-消费者队列中?它似乎是如此低效和缓慢,(因为它是)。数据不能被缓冲以增加传输的数据的大小,从而减少线程间的通信开销吗?在我的例子中,它们不能。我发送的数据存储了有关用户生成的输入事件的信息(在远程计算机上),因此应该(理想情况下)实时处理。Righht。。所以你被困在这里了。好的,那么一个形成循环队列的事件容器呢?您可以加载下一个空闲元素,然后将其地址推送到队列中。然后,用户/主设备可以解除对其的锁定。它仍然会效率低下,但至少可以避免新建/删除微小结构的痛苦。我大致知道thread2生成事件的频率,以及main使用事件的频率。所以我知道循环队列应该有多大。您的解决方案很好,谢谢(-:好的,我将把它推广到实际的答案,然后:)这段代码很难理解。我认为没有理由操纵虚拟值的地址。我宁愿这样做:
//全局?Uint8队列_环[10];int queue_index=0//thread2 queue\u ring[queue\u index]=UInt8Value;event.user.data=&queue_ring[队列索引];队列索引=(队列索引+1)%10;SDL_PushEvent(&event);//main Uint8 Uint8 value=*(Uint8*)event.user.data这个解决方案很有趣,尽管如果有10个以上的变量挂起,代码将失败。我的代码不会。虚拟_值实际上不用于保存任何内容。在C语言中,您不必将整数转换为指针。但是,如果使用数组,则可以从指针转换为偏移量,如果偏移量小于数组中的元素数,则可以从偏移量转换为指针。这里我们知道我们的偏移量最大为255(因为它是uint8)。因此,我们可以通过将偏移量添加到伪值的起始地址,将每个值转换为有效指针。我们把这个过程倒过来转换回去。