Multithreading 强制消息循环屈服

Multithreading 强制消息循环屈服,multithreading,concurrency,ada,Multithreading,Concurrency,Ada,我希望这个问题不要太宽泛 我正在使用一个遗留的Ada应用程序。该应用程序是围绕一个非常古老的中间件构建的,该中间件处理IPC等事务。为了解决这个问题,我可以将中间件的规定归结为 1:处理消息(来自其他程序或此程序)的消息循环 2:向该程序或其他程序发送消息的功能 3:从数据库读取的函数 该程序主要在一个消息循环上运行-简单地说 loop This_Msg := Message_Loop.Wait_For_Message; -- Blocking wait call -- Do

我希望这个问题不要太宽泛

我正在使用一个遗留的Ada应用程序。该应用程序是围绕一个非常古老的中间件构建的,该中间件处理IPC等事务。为了解决这个问题,我可以将中间件的规定归结为

1:处理消息(来自其他程序或此程序)的消息循环

2:向该程序或其他程序发送消息的功能

3:从数据库读取的函数

该程序主要在一个消息循环上运行-简单地说

 loop
    This_Msg := Message_Loop.Wait_For_Message; -- Blocking wait call
    -- Do things based on This_Msg's ID
 end loop
然而,也有一些回调可以由外部刺激触发。这些回调在它们自己的线程中运行。其中一些回调调用数据库读取函数,这一直都很好,但正如我们最近发现的,在一种相对罕见的情况下除外。当出现这种情况时,当消息循环执行其阻塞Wait_For_消息时,从数据库读取数据是不安全的

一个简单的解决方案似乎是使用一个受保护的对象来同步Wait_For_消息和数据库读取:如果我们在Wait_For_消息阻塞时尝试读取数据库,则读取将阻塞,直到Wait_For_消息返回,此时Wait_For_消息调用将被阻塞,直到数据库读取完成。下一个问题是,我不能保证消息循环将及时接收消息,这意味着数据库读取可能会被阻止任意时间。看起来解决这个问题的方法也很简单:在阻塞之前向循环发送一个不做任何事情的消息,确保Wait_For_消息调用将产生

我想说的是:

如果我发送“不做任何事”消息,然后在数据库读取之前阻塞,我想我不能保证Wait_For_消息不会返回、放弃、处理“不做任何事”消息,并在预数据库读取块之前再次开始阻塞。我认为从概念上讲,我需要开始阻塞,然后推送消息,但我不确定如何做到这一点。我想我可以用第二层锁来处理它,但我想不出最有效的方法,也不知道这是否是正确的解决方案。这是我在Ada中第一次尝试并发,所以我希望有一个指向正确方向的指针。

也许你应该为此使用一个任务;下面的任务将在
SELECT
处等待处理消息或访问数据库,而在处理过程中对条目的另一次调用将在该条目上排队等待循环,以重复
SELECT
,从而完全消除问题。。。除非您的DB访问以某种方式调用消息条目;但这不应该发生

包示例是
任务消息处理器正在运行
输入消息(文本:字符串);
输入读取数据库(数据:数据库记录);
终端信息处理机;
结束示例;
包体示例是
任务正文消息\u处理器不可用
包装信息_持有人是新的Ada.Containers.Unlimited_持有人
(元素类型=>字符串);
包装DB_Rec_支架是新的Ada.Containers.Unlimited_支架
(元素类型=>DB\u Rec);
当前_消息:消息_Holder.Holder;
当前数据库记录:数据库记录持有者。持有者;
开始
消息循环:
环
选择
接受消息(文本:字符串形式)do
当前消息:=消息持有者。到消息持有者(文本);
结束消息;
--在**渲染窗口外处理**消息。
延迟1.0;——模拟处理。
Ada.Text\u IO.Put\u行(当前\u Message.Element);
或
接受Read_DB(数据:在DB_Rec中)do
当前数据库记录:=数据库记录持有人。至持有人(数据);
结束消息;
--在此处处理数据库记录,**在渲染区外**。
或
终止
终端选择;
结束循环消息\u循环;
终端信息处理机;
结束示例;
也许你应该为此使用一个任务;下面的任务将在
SELECT
处等待处理消息或访问数据库,而在处理过程中对条目的另一次调用将在该条目上排队等待循环,以重复
SELECT
,从而完全消除问题。。。除非您的DB访问以某种方式调用消息条目;但这不应该发生

包示例是
任务消息处理器正在运行
输入消息(文本:字符串);
输入读取数据库(数据:数据库记录);
终端信息处理机;
结束示例;
包体示例是
任务正文消息\u处理器不可用
包装信息_持有人是新的Ada.Containers.Unlimited_持有人
(元素类型=>字符串);
包装DB_Rec_支架是新的Ada.Containers.Unlimited_支架
(元素类型=>DB\u Rec);
当前_消息:消息_Holder.Holder;
当前数据库记录:数据库记录持有者。持有者;
开始
消息循环:
环
选择
接受消息(文本:字符串形式)do
当前消息:=消息持有者。到消息持有者(文本);
结束消息;
--在**渲染窗口外处理**消息。
延迟1.0;——模拟处理。
Ada.Text\u IO.Put\u行(当前\u Message.Element);
或
接受Read_DB(数据:在DB_Rec中)do
当前数据库记录:=数据库记录持有人。至持有人(数据);
结束消息;
--在此处处理数据库记录,**在渲染区外**。
或
终止
终端选择;
结束循环消息\u循环;
终端信息处理机;
结束示例;
您可以查看采购订单。我试着做了一个例子,但为时已晚(而且我一点也不确定这是否是先验的)