Priority-based queuing in queue block does not work - anylogic

I am trying to use priority based queuing in my queue block. My process is as follows:
source, wait, queue, packing_machine
On exit of the wait block, the agent gets assigned a priority in agent.atrPriority. In queue I have selected Queuing: Priority based and at Agent priority I use: agent.atrPriority.
By printing to the console I am checking if the sequence in which the agents enter the packing_machine block is correct (according to their priority), but it isn't. It keeps sending the agents from queue to packing_station on a FIFO basis.
I have tried assiging agent.atrPriority at different places in the model, but I do not think that that is the problem. i have also tried using agents comparison with agent1.atrPriority.before(agent2.atrPriority); but it gives the error ' Cannot invoke before(int) on the primitive type int.
Does anyone know why it is not working accordingly?

The queue is working, so it is not a bug.
Try a quick test: put another delay between the Wait and the Queue. Set the delay duration to be 0.0001 sec or something tiny.
If this fixes it, the culprit is that you change the atrPriority field "on Exit" of Wait, which is effectively too late. It basically changes after the downstream Queue accesses the priority value.
Another option: change the atrPriority value before you call wait.free(...). This way, you can be sure the priority is set to the right value before the agent enters the queue

Related

StopDelay for cars based on variable value (AnyLogic)

I am trying to stopDelay at delayNucSafe1 (See Screenshot) when the car exits at carMovetoScale1 They way I am currently doing it is at the "On Exit" block of carMovetoScale1 typing: delayNucSafe1 .stopDelay() but I am getting an error that says:
Description: The method stopDelay(Agent) in the type Delay is not applicable for the arguments (). Location: Scale House/Main/carMoveToScale1 - CarMoveTo
Logic Flowchar
where I am asking to stopDelay
Can someone help with this?
The stopDelay(Agent) method is for use when there are multiple agents waiting within the delay and you need to stop the delay for ONE specific agent. If this is the case for you, you would need to know which agent you want to stop the delay for.
For instance, you would call: delayNucSafe1.stopDelay(delayNucSafe1.get(0)) to stop the delay for the agent at index 0 in delayNucSafe1. (This code would also work if there is only 1 agent in the delay).
On the other hand, if you know for sure that there will only ever be 1 agent in the delay (or if you'd like to stop the delay for every agent simultaneously), you would use the method: stopDelayForAll(). This method has the benefit that it doesn't need an argument, but it will obviously cause problems if there are multiple agents waiting in the delay, each of which need to be released independently.
So in summary:
delayNucSafe1.stopDelay(delayNucSafe1.get(agentIndex))
will stop the delay for the agent at index agentIndex within delayNucSafe1. And:
delayNucSafe1.stopDelayForAll()
requires no arguments, and will stop the delay for all agents within delayNucSafe1

Monitors : " At each point in time, at most one thread may be executing any of its methods. "

I've been recently taught, the concept of monitors. My prof, said "only one thread per time can be in the monitor". I am not sure I get this that's why I did my research. Wikipaideia states what i wrote as a title. My book states though, that inside monitor there are queues, for threads that are waiting , until some defined condition is met. What really confused me is a pseudocode we were given as solution to the bounded buffer problem with monitors.
My question is : If a process is not stopped by a wait() inside the monitor, does monitor structure guaruntee us that it will be permitted to execute the whole method without being interrupted by a context switch or just that, while it is executing the method nobody else produce or consumer is executing their according method?? .
Because in this, slide:
It seems like we only wake up a consumer if the buffer was empty, and we just produced an item.
Everytime a producer that reaches that part of code, has produced an item. Why don't we signal everytime? I supposed that , we (may) consider that: if the buffer wasn't empty, then they may be "active" consumers waiting, to be resumed because they were interrupted by a context switch, but then I thought to myself is this possible? Is it possible to be interrupted inside a method (not because you are "waited") but by a context switch?

MTLSharedEventListener block called before command buffer scheduling and not in-flight

I am using a MTLSharedEvent to occasionally relay new information from the CPU to the GPU by writing into a MTLBuffer with storage mode .storageModeManaged within a block registered by the shared event (using the notify(_:atValue:block:) method of MTLSharedEvent, with a MTLSharedEventListener configured to be notified on a background dispatch queue). The process looks something like this:
let device = MTLCreateSystemDefaultDevice()!
let synchronizationQueue = DispatchQueue(label: "com.myproject.synchronization")
let sharedEvent = device.makeSharedEvent()!
let sharedEventListener = MTLSharedEventListener(dispatchQueue: synchronizationQueue)
// Updated only occasionally on the CPU (on user interaction). Mostly written to
// on the GPU
let managedBuffer = device.makeBuffer(length: 10, options: .storageModeManaged)!
var doExtra = true
func computeSomething(commandBuffer: MTLCommandBuffer) {
// Do work on the GPU every frame
// After writing to the buffer on the GPU, synchronize the buffer (required)
let blitToSynchronize = commandBuffer.makeBlitCommandEncoder()!
blitToSynchronize.synchronize(resource: managedBuffer)
blitToSynchronize.endEncoding()
// Occassionally, add extra information on the GPU
if doExtraWork {
// Register a block to write into the buffer
sharedEvent.notify(sharedEventListener, atValue: 1) { event, value in
// Safely write into the buffer. Make sure we call `didModifyRange(_:)` after
// Update the counter
event.signaledValue = 2
}
commandBuffer.encodeSignalEvent(sharedEvent, value: 1)
commandBuffer.encodeWaitForEvent(sharedEvent, value: 2)
}
// Commit the work
commandBuffer.commit()
}
The expected behavior is as follows:
The GPU does some work with the managed buffer
Occasionally, the information needs to be updated with new information on the CPU. In this frame, we register a block of work to be executed. We do so in a dedicated block because we cannot guarantee that by the time execution on the main thread reaches this point the GPU is not simultaneously reading from or writing to the managed buffer. Hence, it is unsafe to simply write to it currently and must make sure the GPU is not doing anything with this data
When the GPU schedules this command buffer to be executed, commands executed before the encodeSignalEvent(_:value:) call are executed and then execution on the GPU stops until the block increments the signaledValue property of the event passed into the block
When execution reaches the block, we can safely write into the managed buffer because we know the CPU has exclusive access to the resource. Once we've done so, we resume execution of the GPU
The issue is that it seems Metal is not calling the block when the GPU is executing the command, but rather before the command buffer is even scheduled. Worse, the system seems to "work" with the initial command buffer (the very first command buffer, before any other are scheduled).
I first noticed this issue when I looked at a GPU frame capture after my scene would vanish after a CPU update, which is where I saw that the GPU had NaNs all over the place. I then ran into this strange situation when I purposely waited on the background dispatch queue with a sleep(:_) call. Quite correctly, my shared resource semaphore (not shown, signaled in a completion block of the command buffer and waited on in the main thread) reached a value of -1 after committing three command buffers to the command queue (three being the number of recycled shared MTLBuffers holding scene uniform data etc.). This suggests that the first command buffer has not finished executing by then time the CPU is more than three frames ahead, which is consistent with the sleep(_:) behavior. Again, what isn't consistent is the ordering: Metal seems to call the block before even scheduling the buffer. Further, in subsequent frames, it doesn't seem that Metal cares that the sharedEventListener block is taking so long and schedules the command buffer for execution even while the block is running, which finishes dozens of frames later.
This behavior is completely inconsistent with what I expect. What is going on here?
P.S.
There is probably a better way to periodically update a managed buffer whose contents are mostly
modified on the GPU, but I have not yet found a way to do so. Any advice on this subject is appreciated as well. Of course, a triple buffer system could work, but it would waste a lot of memory as the managed buffer is quite large (whereas the shared buffers managed by the semaphore are quite small)
I think I have the answer for you, but I'm not sure.
From MTLSharedEvent doc entry
Commands waiting on the event are allowed to run if the new value is equal to or greater than the value for which they are waiting. Similarly, setting the event's value triggers notifications if the value is equal to or greater than the value for which they are waiting.
Which means, that if you are passing values 1 and 2 like you show in your snippet, if will only work a single time and then the event won't be waited and listeners won't be notified.
You have to make sure the value you are waiting on and then signaling is monotonically rising every time, so you have to bump it up by 1 or more.

How I can match bags an passenger in the reclaim area?

I'm simulating a security control process, and i can't do that each passenger pickup their baggage. I have tried with Match, Combine, Pickup, but I still can't execute the commands correctly.
I've created the follow flowchart, and the problem is in the wReclaimPax, pickup and wReclaimBags blocks (you can see them in the picture).
https://ibb.co/v3V57Tm
I saw this link Anylogic - Combined multiple items back to original owner to understand something, but I still need help.
I've created 3 functions:
isMatch:
if(equipaje.pasajeroLink.equals(pasajero.equipajeLink)){
return true;
}
return false;
paxBags:
for(int i=0;i<wait.size();i++){
Pasajero p=(Pasajero)wait.get(i);
if(isMatch(p,bag))
return p;
}
return null;
bagsPax:
for(int i=0;i<wait.size();i++){
Equipaje e=(Equipaje)wait.get(i);
if(isMatch(pasajero,e))
return e;
}
return null;
Assumed context
You haven't really explained how your code is related to your process but I'm assuming the following:
Because this is luggage-retrieval, you want to ensure that a passenger
agent (Pasajero) only enters the Pickup block (representing taking bag from
carousel) when his bag (Equipaje agent by the look of it) has
arrived into the wReclaimBag Wait, and been released from it to
queue4 Queue.
For this you need triggers (to remove agents from Wait blocks) when
either a passenger (Pasajero) arrives in wReclaimPax Wait, or a bag (Equipaje) arrives
in the wReclaimBag Wait (because you don't know whether the passenger or their bag will get to their respective Wait blocks first).
So your paxBags function is called in on-entry action of the wReclaimBag Wait, and your bagsPax function in the on-entry action of the wReclaimPax Wait.
Possible problems with current approach
Without knowing more of your model it's hard to say but problems I can think of based on what you've supplied are:
Your functions return the Pasajero or Equipaje if there is one that matches. Your match check relies seemingly on bidirectional connections (links) between Pasajero and Equipaje. Obviously if they're not setup properly the model won't work and, if you're using bidirectional connections you shouldn't need to check both ends.
Your functions need calling so that, if they return non null, they then free the matching agent from the other Wait block, and free themselves. Are you doing that? Without checking, there may be issues with calling free for yourself as you enter a Wait block (since this kind of depends on AnyLogic internals as to whether you count as being 'in' the block at this stage and can be freed). If this seems to be the problem you could create a timeout 0 dynamic event instance to do the free so that you're not doing it within the scope of the on-enter action.
Your pickup block (since it's been setup so that the entering agent will always want to pickup the first agent (Equipaje) in queue4) just needs to be set as waiting for quantity 1 (though see below).
If you've done all this the most likely problem is that the underlying events ordering of AnyLogic is affecting things. When you free agents I'm fairly sure the freeing actually happens in a timeout 0 event scheduled under-the-covers. So it may be that the passenger arrives at the Pickup before their Equipment arrives in queue4 though, if you set the Pickup to be "Exact quantity (wait for)", with quantity of 1, it should handle that.
The animation of the process (numbers in/out/within each block and details when clicking on blocks) should also help you debug what is going wrong; e.g., are bags being left in the Wait when they should have been released, etc.
P.S. With this kind of thing you should always create a minimal example model to make testing the issue/solution easier (and for sharing in help forums such as this where the rest of the complexity of your model is irrelevant). Often you find the problem 'naturally' in the process of trying to construct such a model that reproduces your problem in a minimal way.

Swift: Accessibility: How can I queue events to be executed in sequence?

I want to know if there is a way to queue up accessibility readouts or element focus events one after another.
If I use either: UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, "My Error Message")
or:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.continueButton)
The second call will interrupt the readout that is currently being read.
And obviously, if you use Dispatch with Delay, it's not robust, because different languages have different lengths of content, and also the user has a different readout speed set, which may be set to very slow. So how can I "queue up" multiple focus/read out events and ensure that only one of them gets read out at a time in sequence?
After you post your first announcement you need to wait for UIAccessibilityAnnouncementDidFinishNotification (see more here) before you post the 2nd one.
So build a queue (a set could do it) and whenever UIAccessibilityAnnouncementDidFinishNotification is triggered by the system just pop the first notification in your set (if present) and fire it away.