Use a Queue to Communicate Between Threads in D - multithreading

It is easy enough in D to create a Queue type using the std.container.dlist.
I would like to have multiple threads but have them communicate with a queue, not with message passing (https://tour.dlang.org/tour/en/multithreading/message-passing). As I understand it the messages are designed to always receive data at particular points in the code; the receiving thread will block until the expected data is received.
(EDIT: I was informed about receiveTimeout but having a no timeout and just a check is really more appropriate in this case (maybe a timeout of 0?). Also I am not sure what the message API will do if multiple messages are sent before any any are received. I will have to play with that.)
void main() {
spawn(&worker, thisTid);
// This line will block until the expected message is received.
receive (
(string message) {
writeln("Received the message: ", text);
},
)
}
What I am needing is to merely receive data if there is some. Something like this:
void main() {
Queue!string queue// custom `Queue` type based on DList
spawn(&worker, queue);
while (true) {
// Go through any messages (while consuming `queue`)
for (string message; queue) {
writeln("Received a message: ", text);
}
// Do other stuff
}
}
I have tried using shared variables (https://tour.dlang.org/tour/en/multithreading/synchronization-sharing) but DMD is complaining that "Aliases to mutable thread-local data not allowed." or some other errors, depending.
How would this be done in D? Or, is there a way to use messages to do this kind of communication?

This doesn't answer the specific question but ti does clear up what I think is a misunderstanding of the message passing api...
just call receiveTimeout instead of plain receive
http://dpldocs.info/experimental-docs/std.concurrency.receiveTimeout.html

I use this:
shared class Queue(T) {
private T[] queue;
synchronized void opOpAssign(string op)(T object) if(op == "~") {
queue ~= object;
}
synchronized size_t length(){
return queue.length;
}
synchronized T pop(){
assert(queue.length, "Please check queue length, is 0");
auto first = queue[0];
queue = queue[1..$];
return first;
}
synchronized shared(T[]) consume(){
auto copy = queue;
queue = [];
return copy;
}
}

I have gotten the answer I need.
Simply put, use core.thread rather than std.concurrency. std.concurrency manages messages for you and does not allow you to manage it yourself. core.thread is what std.concurrency uses internally.
The longer answer, here is how I fully implemented it.
I have created a Queue type that is based on an Singly Linked List but maintains a pointer of the last element. The Queue also uses standard component inputRange and outputRange (or at least I think it does) per Walter Brights vision (https://www.youtube.com/watch?v=cQkBOCo8UrE).
The Queue is also built to allow one thread to write and another to read with very little mutexing internally so it should be fast.
The Queue I shared here https://pastebin.com/ddyPpLrp
A simple implementation to have a second thread read input:
Queue!string inputQueue = new Queue!string;
ThreadInput threadInput = new ThreadInput(inputQueue);
threadInput.start;
while (true) {
foreach (string value; inputQueue) {
writeln(value);
}
}
ThreadInput being defined as thus:
class ThreadInput : Thread {
private Queue!string queue;
this(Queue!string queue) {
super(&run);
this.queue = queue;
}
private void run() {
while (true) {
queue.put(readln);
}
}
}
The code https://pastebin.com/w5jwRVrL
The Queue again https://pastebin.com/ddyPpLrp

Related

How to sleep/wait within an app without making the UI unresponsive

I'm developing an app for Windows in Visual C++ which would get inputs from a web API. Some of the API calls require me to request response in some specified time delay and during this time I would like to display a spinner.
I'm all good with the displaying spinner, disabling the buttons etc for the time I need to wait before proceeding to the request, but don't know how to pause the process within the app. Obviously, if I use the _sleep function, the app becomes unresposive.
Here's more or less what I need to achieve (pseudo-code)
void doSomething()
{
ui->button1->setEnable(false);
SendAPIReuqest1();
while (APIRequest1_success)
{
requestAPIRequest1_response();
//wait 10s if false and retry, this can take up to 5mins
}
SendAPIRequest2();
//wait 30s - here I know I can start the job on my end exactly after 30s
doSometing2();
ui->button1->setEnable(true);
}
What would be the correct approach to achieve what I need?
You'll most likely just want to poll for a response from the web API, alternatively you can start a secondary thread to check for a response from the web API;
After seeing some minimal code, something similar to this may work.
//takes an initial start time, calculates elapsed time, compares elapsed time to count
bool ready(std::chrono::time_point<std::chrono::system_clock>&start, const double& count) {
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> diff = end-start;
if (diff.count() >= count) {
start = end;
return true;
}
return false;
}
void doSomething()
{
static std::chrono::time_point<std::chrono::system_clock> start;
static int state = 0;
switch(state) {
case (0):
ui->button1->setEnable(false);
SendAPIRequest1();
if (APIRequest1_success) {
start = std::chrono::system_clock::now();
++state;
}
break;
case (1):
if (ready(start, 10.0) && requestAPIRequest1_response()) ++state;
break;
case(2):
SendAPIRequest2();
start = std::chrono::system_clock::now();
++state;
break;
case(3):
if (ready(start, 30.0)) {
doSomething2();
ui->button1->setEnable(true);
state = 0;
}
break;
}
}
This way you can call the function and it will either attempt one of the requests or return to do other tasks.
or with threads it could be as simple as
void worker_func(std::promise<bool>&& result) {
using namespace std::chrono_literals;
SendAPIRequest1();
while (!requestAPIRequest1_response()) {
std::this_thread::sleep_for(10s);
}
SendAPIRequest2();
std::this_thread::sleep_for(30s);
doSomething2();
result.set_value(true);
}
void doSomething() {
static std::future<bool> finished;
static bool flag = true;
if (flag) {
std::promise<bool> _finished;
finished = _finished.get_future();
ui.button1.setEnable(false);
std::thread worker(worker_func, std::move(_finished));
flag = false;
} else if (finished.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
//finished.get();
worker.join();
ui.button1.setEnable(true);
flag = true;
}
}
This way your main thread can keep running the ui, while the worker thread waits for the web API response, as long as your requests aren't handling any QT ui components I believe this should work.
Edit:
Since I have never used QT and it was never mentioned originally that QT was being used the above answers may or may not be usefull, however it looks like QT has some functions to handle things like this. maybe you can just start and stop a Qtimer
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &foo::update);
timer->start(1000);
would run the function foo::update() every second, the time interval can be changed accordingly. Here is a reference to QTimer and a reference to another class which may be of interest QTimerEvent not to mention, QT has an entire event handling system The Event System

Perform (part of) a static function on a specific thread

I have a function(be it a static function or totally unaffiliated one) and a specific thread
class AnyClass{
static func foo(myThread: NSThread) {
....
// I want this *blablabla* to be performed on myThread
....
}
}
How can I make is happen?
Don't use thread, use dispatch queue (Grand Central Dispatch) instead. See Apple's documentation on Migrating away from threads.
A typical usage pattern for GCD is:
class AnyClass{
static func foo(queue: dispatch_queue_t) {
....
let group = dispatch_group_create();
dispatch_group_enter(group) // tell the OS your group has started
dispatch_group_async(group, queue) {
// Do your things on a different queue
....
dispatch_group_leave(group) // tell the OS your group has ended
}
// Do your other things on the original thread simultaneously
....
dispatch_group_wait(group, DISPATCH_TIME_FOREVER) // wait for the queue to finish
// Do other things still
....
}
}
// Calling the function
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
AnyClass.foo(queue)

From C# after getting IBM MQ message how to identify message data type? Is it Object or String type?

In our company we are using IBM MQ server for message queueing. For the same queue we are putting both String and Object type data message with the help of methods WriteObject and WriteString.
The challenge is occured when it comes to consumption(read message) of queue. Since the Get data can be both Object or String we need to decide which method to use ReadString or ReadObject on the MQMessage instance. I made workaround like firstly using ReadObject method, if an exception occured then try it with ReadString.
I did not like this workaround, is there any way to identify message data type after calling MQQueue instance's Get method?
Here below you can find my workaround:
public object GetMessage(string queueName) {
MQQueueManager queueManager = new MQQueueManager("queueManagerName", "channel", "connection");
MQGetMessageOptions queueGetMessageOptions = new MQGetMessageOptions();
queueGetMessageOptions.Options = MQC.MQGMO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING + MQC.MQPMO_SYNCPOINT;
try {
queueRead = queueManager.AccessQueue(queueName, MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING);
queueMessage = new MQMessage();
queueMessage.Format = MQC.MQFMT_STRING;
queueRead.Get(queueMessage, queueGetMessageOptions);
try {
var readObject = queueMessage.ReadObject();
return readObject;
} catch (SerializationException) { } // if message in queue not a object
queueMessage.DataOffset = 0;
var stringMsg = queueMessage.ReadString(queueMessage.MessageLength);
return stringMsg;
} catch (MQException exp) {
if (exp.ReasonCode != 2033) {
log.ErrorFormat("MQException: ResonCode: {0}, {1}", exp.ReasonCode, exp.Message);
}
}
return "";
}
What a horrible design.
First off, why are you putting 2 different message types into the same queue? Bad, very bad idea. You should be using 2 different queues. What, does someone think queues are scarce or rare? You should be handing out queues like candy.
Secondly, if you really need to go with this design then you should read the MQ Knowledge Center on MQMD structure. It contains a field called 'Message Type'. Most applications use 'Message Type' to contain either 'MQMT_DATAGRAM' or 'MQMT_REQUEST' but you can set your own values starting with 'MQMT_APPL_FIRST'.
So, define a couple of constants:
public const int MY_MSG_OBJECT = MQC.MQMT_APPL_FIRST + 1;
public const int MY_MSG_STRING = MQC.MQMT_APPL_FIRST + 2;
Hence, the sending application putting a string message would do:
MQMessage sendmsg = new MQMessage();
sendmsg.Format = MQC.MQFMT_STRING;
sendmsg.MessageType = MY_MSG_STRING;
sendmsg.WriteString("This is a test message");
queue.Put(sendmsg, pmo);
and the sending application putting an object message would do:
MQMessage sendmsg = new MQMessage();
sendmsg.Format = MQC.MQFMT_NONE;
sendmsg.MessageType = MY_MSG_OBJECT;
sendmsg.WriteObject(someObject);
queue.Put(sendmsg, pmo);
The receiving application would do:
MQMessage rcvmsg = new MQMessage();
queue.Get(rcvmsg, gmo);
// Check the Message Type
if (rcvmsg.MessageType == MY_MSG_STRING)
{
readString = queue.ReadString();
}
else if (rcvmsg.MessageType == MY_MSG_OBJECT)
{
readObject = queue.ReadObject();
}
else
{
System.Console.Out.WriteLine("Error: Unknown message type.");
}

Winforms updates with high performance

Let me setup this question with some background information, we have a long running process which will be generating data in a Windows Form. So, obviously some form of multi-threading is going to be needed to keep the form responsive. But, we also have the requirement that the form updates as many times per second while still remaining responsive.
Here is a simple test example using background worker thread:
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
int reportValue = (int)e.UserState;
label1.Text = reportValue;
//We can put this.Refresh() here to force repaint which gives us high repaints but we lose
//all other responsiveness with the control
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int x = 0; x < 100000; x++)
{
//We could put Thread.Sleep here but we won't get highest performance updates
bw.ReportProgress(0, x);
}
}
Please see the comments in the code. Also, please don't question why I want this. The question is simple, how do we achieve the highest fidelity (most repaints) in updating the form while maintaining responsiveness? Forcing the repaint does give us updates but we don't process windows messages.
I have also try placing DoEvents but that produces stack overflow. What I need is some way to say, "process any windows messages if you haven't lately". I can see also that maybe a slightly different pattern is needed to achieve this.
It seems we need to handle a few issues:
Updating the Form through the non UI thread. There are quite a few solution to this problem such as invoke, synchronization context, background worker pattern.
The second problem is flooding the Form with too many updates which blocks the message processing and this is the issue around which my question really concerns. In most examples, this is handles trivially by slowing down the requests with an arbitrary wait or only updating every X%. Neither of these solutions are approriate for real-world applications nor do they meet the maximum update while responsive criteria.
Some of my initial ideas on how to handle this:
Queue the items in the background worker and then dispatch them in a UI thread. This will ensure every item is painted but will result in lag which we don't want.
Perhaps use TPL
Perhaps use a timer in the UI thread to specify a refresh value. In this way, we can grab the data at the fastest rate that we can process. It will require accessing/sharing data across threads.
Update, I've updated to use a Timer to read a shared variable with the Background worker thread updates. Now for some reason, this method produces a good form response and also allows the background worker to update about 1,000x as fast. But, interestingly it only 1 millisecond accurate.
So we should be able to change the pattern to read the current time and call the updates from the bw thread without the need for the timer.
Here is the new pattern:
//Timer setup
{
RefreshTimer.SynchronizingObject = this;
RefreshTimer.Elapsed += RefreshTimer_Elapsed;
RefreshTimer.AutoReset = true;
RefreshTimer.Start();
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int x = 0; x < 1000000000; x++)
{
//bw.ReportProgress(0, x);
//mUiContext.Post(UpdateLabel, x);
SharedX = x;
}
}
void RefreshTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
label1.Text = SharedX.ToString();
}
Update And here we have the new solution that doesn't require the timer and doesn't block the thread! We achieve a high performance in calculations and fidelity on the updates with this pattern. Unfortunately, ticks TickCount is only 1 MS accurate, however we can run a batch of X updates per MS to get faster then 1 MS timing.
void bw_DoWork(object sender, DoWorkEventArgs e)
{
long lastTickCount = Environment.TickCount;
for (int x = 0; x < 1000000000; x++)
{
if (Environment.TickCount - lastTickCount > 1)
{
bw.ReportProgress(0, x);
lastTickCount = Environment.TickCount;
}
}
}
There is little point in trying to report progress any faster than the user can keep track of it.
If your background thread is posting messages faster than the GUI can process them, (and you have all the symtoms of this - poor GUI resonse to user input, DoEvents runaway recursion), you have to throttle the progress updates somehow.
A common approach is to update the GUI using a main-thread form timer at a rate sufficiently small that the user sees an acceptable progress readout. You may need a mutex or critical section to protect shared data, though that amy not be necessary if the progress value to be monitored is an int/uint.
An alternative is to strangle the thread by forcing it to block on an event or semaphore until the GUI is idle.
The UI thread should not be held for more than 50ms by a CPU-bound operation taking place on it ("The 50ms Rule"). Usually, the UI work items are executed upon events, triggered by user input, completion of an IO-bound operation or a CPU-bound operation offloaded to a background thread.
However, there are some rare cases when the work needs to be done on the UI thread. For example, you may need to poll a UI control for changes, because the control doesn't expose proper onchange-style event. Particularly, this applies to WebBrowser control (DOM Mutation Observers are only being introduced, and IHTMLChangeSink doesn't always work reliably, in my experience).
Here is how it can be done efficiently, without blocking the UI thread message queue. A few key things was used here to make this happen:
The UI work tasks yields (via Application.Idle) to process any pending messages
GetQueueStatus is used to decide on whether to yield or not
Task.Delay is used to throttle the loop, similar to a timer event. This step is optional, if the polling needs to be as precise as possible.
async/await provide pseudo-synchronous linear code flow.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinForms_21643584
{
public partial class MainForm : Form
{
EventHandler ContentChanged = delegate { };
public MainForm()
{
InitializeComponent();
this.Load += MainForm_Load;
}
// Update UI Task
async Task DoUiWorkAsync(CancellationToken token)
{
try
{
var startTick = Environment.TickCount;
var editorText = this.webBrowser.Document.Body.InnerText;
while (true)
{
// observe cancellation
token.ThrowIfCancellationRequested();
// throttle (optional)
await Task.Delay(50);
// yield to keep the UI responsive
await ApplicationExt.IdleYield();
// poll the content for changes
var newEditorText = this.webBrowser.Document.Body.InnerText;
if (newEditorText != editorText)
{
editorText = newEditorText;
this.status.Text = "Changed on " + (Environment.TickCount - startTick) + "ms";
this.ContentChanged(this, EventArgs.Empty);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
async void MainForm_Load(object sender, EventArgs e)
{
// navigate the WebBrowser
var documentTcs = new TaskCompletionSource<bool>();
this.webBrowser.DocumentCompleted += (sIgnore, eIgnore) => documentTcs.TrySetResult(true);
this.webBrowser.DocumentText = "<div style='width: 100%; height: 100%' contentEditable='true'></div>";
await documentTcs.Task;
// cancel updates in 10 s
var cts = new CancellationTokenSource(20000);
// start the UI update
var task = DoUiWorkAsync(cts.Token);
}
}
// Yield via Application.Idle
public static class ApplicationExt
{
public static Task<bool> IdleYield()
{
var idleTcs = new TaskCompletionSource<bool>();
if (IsMessagePending())
{
// register for Application.Idle
EventHandler handler = null;
handler = (s, e) =>
{
Application.Idle -= handler;
idleTcs.SetResult(true);
};
Application.Idle += handler;
}
else
idleTcs.SetResult(false);
return idleTcs.Task;
}
public static bool IsMessagePending()
{
// The high-order word of the return value indicates the types of messages currently in the queue.
return 0 != (GetQueueStatus(QS_MASK) >> 16 & QS_MASK);
}
const uint QS_MASK = 0x1FF;
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern uint GetQueueStatus(uint flags);
}
}
This code is specific to WinForms. Here is a similar approach for WPF.

How do I block access to a method until animations are complete

I have a Silverlight app. that has a basic animation where a rectangle is animated to a new position. The animation consists of two DoubleAnimation() - one transforms the X, the other transforms the Y. It works OK.
I basically want to block any other calls to this animate method until the first two animations have completed. I see that the DoubleAnimation() class has a Completed event it fires but I haven't been successful in constructing any kind of code that successfully blocks until both have completed.
I attempted to use Monitor.Enter on a private member when entering the method, then releasing the lock from one of the animations Completed event, but my attempts at chaining the two events (so the lock isn't released until both have completed) haven't been successful.
Here's what the animation method looks like:
public void AnimateRectangle(Rectangle rect, double newX, double newY)
{
var xIsComplete = false;
Duration duration = new Duration(new TimeSpan(0, 0, 0, 1, 350));
var easing = new ElasticEase() { EasingMode = EasingMode.EaseOut, Oscillations = 1, Springiness = 4 };
var animateX = new DoubleAnimation();
var animateY = new DoubleAnimation();
animateX.EasingFunction = easing;
animateX.Duration = duration;
animateY.EasingFunction = easing;
animateY.Duration = duration;
var sb = new Storyboard();
sb.Duration = duration;
sb.Children.Add(animateX);
sb.Children.Add(animateY);
Storyboard.SetTarget(animateX, rect);
Storyboard.SetTargetProperty(animateX, new PropertyPath("(Canvas.Left)"));
Storyboard.SetTarget(animateY, rect);
Storyboard.SetTargetProperty(animateY, new PropertyPath("(Canvas.Top)"));
animateX.To = newX;
animateY.To = newY;
sb.Begin();
}
EDIT (added more info)
I ran into this initially because I was calling this method from another method (as it processed items it made a call to the animation). I noticed that the items didn't end up where I expected them to. The new X/Y coordinates I pass in are based on the items current location, so if it was called multiple times before it finished, it ended up in the wrong location. As a test I added a button that only ran the animation once. It worked. However, if I click on the button a bunch of times in a row I see the same behavior as before: items end up in the wrong location.
Yes, it appears Silverlight animations are run on the main UI thread. One of the tests I tried I added two properties that flagged whether both animations had completed yet. In the AnimateRectange() method I checked them inside of a while loop (calling Thread.Sleep). This loop never completed (so it's definitely on the same thread).
So I created a queue to process the animations in order:
private void ProcessAnimationQueue()
{
var items = this.m_animationQueue.GetEnumerator();
while (items.MoveNext())
{
while (this.m_isXanimationInProgress || this.m_isYanimationInProgress)
{
System.Threading.Thread.Sleep(100);
}
var item = items.Current;
Dispatcher.BeginInvoke(() => this.AnimateRectangle(item.Rect.Rect, item.X, item.Y));
}
}
Then I call my initial routine (which queues up the animations) and call this method on a new thread. I see the same results.
As far as I am aware all of the animations in Silverlight are happening on the UI thread anyway. I am guessing that only the UI thread is calling this animation function anyway, so I am not sure that using locking will help. Do you really want to be blocking the entire thread or just preventing another animation from starting?
I would suggest something more like this:
private bool isAnimating = false;
public void AnimateRectangle(Rectangle rect, double newX, double newY)
{
if (isAnimating)
return;
// rest of animation code
sb.Completed += (sender, e) =>
{
isAnimating = false;
};
isAnimating = true;
sb.Begin();
}
Just keep track of whether or not you are currently animating with a flag and return early if you are. If you don't want to lose potential animations your other option is to keep some kind of a queue for animation which you could check/start when each animation has completed.
This question really peaked my interest. In fact I'm going to include it in my next blog post.
Boiling it down, just to be sure we are talking about the same thing, fundementally you don't want to block the call to AnimateRectangle you just want to "queue" the call so that once any outstanding call has completed its animation this "queued" call gets executed. By extension you may need to queue several calls if a previous call hasn't even started yet.
So we need two things:-
A means to treat what are essentially asynchronous operations (sb.Begin to Completed event) as a sequential operation, one operation only starting when the previous has completed.
A means to queue additional operations when one or more operations are yet to complete.
AsyncOperationService
Item 1 comes up in a zillion different ways in Silverlight due to the asynchronous nature of so many things. I solve this issue with a simple asynchronous operation runner blogged here. Add the AsyncOperationService code to your project.
AsyncOperationQueue
Its item 2 that really took my interest. The variation here is that whilst an existing set of operations are in progress there is demand to add another. For a general case solution we'd need a thread-safe means of including another operation.
Here is the bare-bones of a AsyncOperationQueue:-
public class AsyncOperationQueue
{
readonly Queue<AsyncOperation> myQueue = new Queue<AsyncOperation>();
AsyncOperation myCurrentOp = null;
public void Enqueue(AsyncOperation op)
{
bool start = false;
lock (myQueue)
{
if (myCurrentOp != null)
{
myQueue.Enqueue(op);
}
else
{
myCurrentOp = op;
start = true;
}
}
if (start)
DequeueOps().Run(delegate { });
}
private AsyncOperation GetNextOperation()
{
lock (myQueue)
{
myCurrentOp = (myQueue.Count > 0) ? myQueue.Dequeue() : null;
return myCurrentOp;
}
}
private IEnumerable<AsyncOperation> DequeueOps()
{
AsyncOperation nextOp = myCurrentOp;
while (nextOp != null)
{
yield return nextOp;
nextOp = GetNextOperation();
}
}
}
Putting it to use
First thing to do is convert your existing AnimateRectangle method into a GetAnimateRectangleOp that returns a AsyncOperation. Like this:-
public AsyncOperation GetAnimateRectangleOp(Rectangle rect, double newX, double newY)
{
return (completed) =>
{
// Code identical to the body of your original AnimateRectangle method.
sb.Begin();
sb.Completed += (s, args) => completed(null);
};
}
We need to hold an instance of the AsyncOperationQueue:-
private AsyncOperationQueue myAnimationQueue = new AsyncOperationQueue();
Finally we need to re-create AnimateRectangle that enqueues the operation to the queue:-
public void AnimateRectangle(Rectangle rect, double newX, double newY)
{
myAnimationQueue.Enqueue(GetAnimateRectangleOp(rect, newX, newY)
}

Resources