(Anylogic) How to reference Main from another agent - reference

How Do I Reference Main From Within An Agent?
I have a resourcepool of 1 of an agent moving items in Main. There the process is modelled with The Process Modelling Library. The Agent does neither Enter not Exit the Process Model, but perists indefinitely.
I now wish to add a statechart to my agent, in which I want to test if the agent arrived at a certain Queue Block in Main. However, I cannot reference Main from my agent's statechart. Neither 'get_Main()' nor 'main' work, as I also don't have the arrow with main on it (I have seen this on reference models).I'm using Anylogic 8.1 The main arrow I found in reference models
Edit: solution i found: Use a variable and set it to Main, you can reference items in Main over this variable.

Two options:
embedd an agent population on Main and make your ResourcePool add agents to that on creation. This will give you the main link
Use getEngine().getRoot() at any point in your model. As long as your top-level agent is Main (normal case), this will work. You may have to type-cast it as ((Main)getEngine().getRoot())

Related

there is __cond_lock(x,c) define in compiler.h file , but no __cond_unlock(x,c) define?

In complier.h, there is a macro define as below:
# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
But here I have a question, that is, where there is a __cond_lock definition, but does not define the corresponding __cond_unlock, then the variable on the release, how to keep consistent between __cond_lock and __cond_unlock?
And I checked the definition of function spin_trylock (), and it is used __cond_lock, but which also used a _spin_trylock function.in _spin_trylock function, after a few calls, it will use to __acquire function in this case, the equivalent of an operation, it carried out two calculations would lead Sparse detection warning message appears, after I wrote the code for an experiment to test my judgment, is indeed a warning message will appear, if I wrote it twice unlock instruction, there is no alarm information, but this is inconsistent as program running.
Protecting critical sections using locking is up to the programmer. That means, if you hold a lock to protect a critical reason, you've must have to release the lock when you're finished.
There are various types of locking primitives inside Linux kernel like. spinlock(), spinlock_irq(), spin_trylock(). They have their own purposes. Now, spin_trylock() using __cond_lock inside of it, it's because to make sure, whether that particular lock is available for locking or it's been already taken. Take a look at few examples of how spin_trylock or __cond_lock is being used. For ex. at kernel/sched/fair.c::rebalance_domain (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/kernel/sched/fair.c?id=d8dfad3876e4386666b759da3c833d62fb8b2267#n5574) see how the balancing is used, it's been using spin_trylock() to hold the lock and while releasing doing it conditionally. Another example could be found at kernel/posix-timers.c, lock_timer() macro. If you closely look at the uses of lock_timer() you'll find how __cond_lock is being used inside kernel and hopefully your confusion will disappear.
In other words, __cond_lock is used to hold a lock conditionally and not being used directly. It's possible to check a particular lock before releasing the lock and this what has been done so far.

How can I delete and deallocate OVM objects in SystemVerilog?

I would like to delete an ovm object (and its children) so that I can recreate it with different configs. Is there a way to do this in OVM?
Currently, when I try to create the object a second time with new, I get the following VCS runtime error:
[CLDEXT] Cannot set 'ap' as a child of 'instance', which already has a child by that name.
I realize that I can simply use a different name to "re-create" the instance, but then I'll still have the old instance sitting around and soaking up memory.
OVM is just a SystemVerilog library. That means that all the rules of SystemVerilog apply to OVM. So, yes, you can use new() with OVM. Sometimes it's preferable to use the factory, and sometimes it's preferable to use new() (that's a topic for a different discussion).
SystemVerilog does not have a delete operator or a destructor like C++. Instead, when you are done with an object you just remove all references to it and the garbage collector will clean up the memory. Here's a quote from the SystemVerilog reference manual (IEEE 1800-2009) section 8.7:
SystemVerilog does not require the complex memory allocation and deallocation of C++. Construction of an object is straightforward; and garbage collection, as in Java, is implicit and automatic. There can be no memory leaks or other subtle behaviors, which are so often the bane of C++ programmers.
It's not entirely true that you cannot have a memory leak. You can forget to remove all references to an object and the garbage collector will not know to pick it up. However, you do not have to worry about memory with the same detail as you do in C++.
The particular error you received with id CLDEXT is from ovm_component class. From the message it appears that you attempted to create two components with the same name and the same parent. Components in OVM are typically static. That is, you create and elaborate them once, usually at time 0, and don't delete or add components after that. Because of this model there are no methods in ovm_component to remove child components. So there really isn't a good way to replace a component once it has been instantiated. By the way, this only applies to components. Other types of objects can be re-allocated.
If you feel that you need to replace a component with a different one after time 0 you should re-think the architecture of your testbench. There are probably betters ways to accomplish what you are trying to do without replacing components.
I have only UVM experience but I think OVM is similar. I would have liked to reply to #Victor Lyuboslavsky's comment but I can't add comments.
The issue is with the name 'ap' which evidently has already been used for a child of 'instance'. Use this code instead.
static int instNum = 0;
instance_ap = my_ovm_extended_class::type_id::create
($sformatf ("ap%0d", instNum), this);
The first time an object is created & the handle assigned to 'instance_ap', the object would have the name 'instance.ap0'. The next time the code executes an object called 'instance.ap1', and so on.
As mentioned by other posters this ought to be done only for non-component objects, and components should be static and must be created during/before the build phase & connected to each other during/before the connect phase.
Try assigning null to the object before calling new again.
Unless I see someone else answer this question, I'd say there is no easy way to deallocate objects in OVM framework.
OVM testbenches are static and created when the testbench is created.
When the environment class is instantiated, it will call new(create), build, connect, end_of_elaboration, start_of_simulation, run and check on all components.
By the end of the environment build phase all components must be created.
By the end of the environment connect phase all components must have their TLM ports connected.
Because of these requirements, you can not change components (or port connections) except for during the phase.
As part of the static nature of the testbench environment, every component must have a unique get_full_name() response. This is because string lookups are used to identify components in the hierarchy.
Assigning an object to null should deallocate memory. If there is no other handle pointing to that memory location, then it should get reclaimed.

Silverlight Multithreading; Need to Synchronize?

I have a Silverlight app where I've implemented the M-V-VM pattern so my actual UI elements (Views) are separated from the data (Models). Anyways, at one point after the user has gone and done some selections and possible other input, I'd like to asyncronously go though the model and scan it and compile a list of optiions that the user has changed (different from the default), and eventually update that on the UI as a summary, but that would be a final step.
My question is that if I use a background worker to do this, up until I actually want to do the UI updates, I just want to read current values in one of my models, I don't have to synchronize access to the model right? I'm not modifying data just reading current values...
There are Lists (ObservableCollections), so I will have to call methods of those collections like "_ABCCollection.GetSelectedItems()" but again I'm just reading, I'm not making changes. Since they are not primitives, will I have to synchronize access to them for just reads, or does that not matter?
I assume I'll have to sychronize my final step as it will cause PropertyChanged events to fire and eventually the Views will request the new data through the bindings...
Thanks in advance for any and all advice.
You are correct. You can read from your Model objects and ObservableCollections on a worker thread without having a cross-thread violation. Getting or setting the value of a property on a UI element (more specifically, an object that derives from DispatcherObject) must be done on the UI thread (more specifically, the thread on which the DispatcherObject subclass instance was created). For more info about this, see here.

How to access thread variable using OmniThreadLibrary?

This seems to be an easy task, I just don't know which way to start using OmniThreadLibrary:
I create a Task that does some processing in the background. The results are stored in fields of the task class and are continuously filled with new values.
Now the main thread wants to read these fields and display their values from time to time.
Therefore it needs to access these fields and make sure that they are not written to at these moments (Synchronize).
How can this be done with OmniThreadLibrary?
There's no direct support for owner/thread data sharing in the OTL, because all my multithreaded experience tells me that this is always a bad thing to do. (Agree, sometimes it is the only solution but still it's a bad thing.)
You should go with the second mghie's suggestion - create an (optionally interface-based) object and pass this object (or its interface) to the thread. Something like this:
sharedData := TSharedData.Create;
task := CreateTask(worker).SetParameter('shared', sharedData).Run;
worker:
sharedData := Task.Param['shared'].AsObject as TSharedData;
Another way to solve the problem would be to send a 'please send update' message to the task whenever the user presses the UpdateNow button. That task would then respond with an object containing current state. However, if the task performs a lengthy uninterruptable calculation this solution is not really appropriate and the shared state approach works better.
Check out the OTL test 23, which implements a background file search. The SetParameter() method is used to set the search properties, the Comm channel is used to transfer results back to the main thread. The communication is already thread-safe, you need not implement any further synchronization.
Edit:
If you don't want a push but a pull model then you can of course use standard synchronization tools: an object that has a critical section which is used in all accessors to protect data from concurrent access. This object could be the task object itself, or any third object that is created by the GUI thread and passed to the task by (again) calling SetParameter(). If you don't use an object but an interface pointer you will get more safety, as the order of destruction is no longer important, the object holding the data will only be destroyed once the last reference to the interface it implements is reset.

QT: QFileSystemModel _q_fileSystemChanged slot is executed on the UI thread which contradicts documentation

My UI is using QTreeView with QFileSystemModel to be able to select folders and files. The documentation for QFileSystemModel says that file structure update is done on a seperate thread which would mean the UI would not be blocked. However, this is not the case for me and I can't figure out the discreptency and how other people are not running into this issue. After debugging, I noticed that QFileSystemModel _q_fileSystemChanged slot which takes most of the time is still executed on the main UI thread which makes sense. The Questiong is how does the documentation claim than that it will not block the UI. Is there a solution? Am I misunderstanding something?
To repro
- Create a QTreeView with QFileSystemDataModel
- Set root path to "" or "/"
- Set breakpoint in QFileSystemModel _q_fileSystemChanged slot
- Expand one of the drives after app loads
Problem:
- The slot is called on the UI thread thus blocking the app until it finishes.
There are ways to make the file parser faster, but it I really need to execute on a seperate thread and notify when the data is populated and ready for QTreeView.
Thanks,
Innokenty
I think the reason for this could be the icons. Within the _q_fileSystemChanged() slot fileInfoGatherer.getInfo() gets called which - among other things - resolves the icons for the paths. In it's current design QFileIconProvider uses QIcon to represent icons and QIcon can only be used in the UI thread. QImage seems to be the only class allowed to use in other threads, but I think it may be to expensive to use QImage in the background thread and convert it to an QIcon in the UI thread.
So it is possible that the platform implementation of QFileIconProvider is slow on network paths under some circumstances and therefore slows down the UI main thread.
I don't know if this is the source of your problem, but at least this should be the reason why _q_fileSystemChanged() is called within the UI thread.

Resources