So there’s a few tricky things here:

   -

   Keeping that old Context around keeps everything that was in that call
   stack around, which is a memory hog, but more importantly could have
   unpredictable consequences depending on the state of the model. For
   instance, if the call to the extension is made by a turtle, and then that
   turtle dies, the context keeps a reference to that turtle, and then has
   that dead turtle running things. Not sure what that entails, but there’s
   undoubtedly a ton of edge cases within that that will have a bunch of
   bizarre behavior.
   -

   It looks like system-hook is using it’s own thread to dispatch from
   rather than the EDT, which is nice, because it avoids common sources of
   deadlocks with NetLogo. However, you still probably don’t want to be
   clogging this thread up with potentially long running NetLogo code (that
   might end up waiting on, for instance, the EDT in some instances, or IO to
   complete, etc). Perhaps more importantly, you also don’t want to end up in
   a case where modifications to the world are happening in both the
   system-hook event thread and the Netlogo job thread. So, the way around
   this is to make sure that all NetLogo stuff actually ends up running on the
   job thread, and not waiting on those jobs to finish.

There’s two ways around this. First, cast the api.AnonymousCommand to an
nvm.AnonymousCommand and grab the Procedure
<https://github.com/NetLogo/NetLogo/blob/hexy/netlogo-core/src/main/nvm/AnonymousProcedure.scala#L133>
out of it. Then you can simply submit this to the job thread directly with
something like (used to writing stuff like this in Scala, so you might have
to change some field accesses to method calls and such):

Job job = workspace.jobManager.makeConcurrentJob(owner,
workspace.world.observers, workspace, procedure);
workspace.jobManager.addJob(job, false);

owner can be a SimpleJobOwner with just the name of your extension or
whatever you like. That second argument to addJob tells it not to wait for
the job to finish.

The downside to this approach is that it doesn’t pass along the local
variable information closed over by the AnonymousCommand. To preserve that
(safely), you’ll have to actually get AnonymousCommand.perform to be called
from the job thread. The only way I know of doing this is to compile a call
to the run primitive with a dummy AnonymousCommand and then swap out the
argument with your AnonymousCommand. Something like this (I don’t have my
IDE with NetLogo code in front of me, so guessing at the conversion to Java
here):

Procedure runner = workspace.compileCommands("(run [ -> ])");
runner.code[0].args[0] = _const(cmd);

where cmd is the AnonymousCommand and _const is org.nlogo.prim._const. You
can then wrap runner in a job and submit to the job thread as above. Note
that that runner does not have to (and probably shouldn’t) be created when
the even actually triggers. Instead, you can create it when the call to the
extension primitive is made.

Hope that helps!
Bryan



On Wed, Jan 8, 2020 at 5:53 AM TechnoRazor <therealtechnora...@gmail.com>
wrote:

> Update: I came up with this, and it seems to work. Are there any potential
> issues that would arise from this?
> org.nlogo.nvm.Context nvmContext = ((org.nlogo.nvm.ExtensionContext)
> context).nvmContext();
> nvmContext.finished = false;
> command.perform(new org.nlogo.nvm.ExtensionContext((Workspace)
> context.workspace(), nvmContext), new Object[0]);
>
> On Wednesday, January 8, 2020 at 6:01:35 AM UTC-5, TechnoRazor wrote:
>>
>> Ah, that makes sense. I'm using my extension to bind anonymous commands
>> to key presses, using the "system-hook" library. The anonymous commands are
>> called from the key pressed event thread. I assume I should create a new
>> Context, but how would I do that?
>>
>> On Tuesday, January 7, 2020 at 11:27:54 PM UTC-5, Bryan Head wrote:
>>>
>>> So I think what’s happening here is that the Context the
>>> AnonymousCommand is created with is ending and thus getting marked
>>> finished. The finished marker is how Contexts know whether or not to
>>> keep executing code. You can see this here:
>>> https://github.com/NetLogo/NetLogo/blob/hexy/netlogo-core/src/main/nvm/Context.java#L128-L137.
>>> Because it’s a do... while rather than a while, it will only
>>> prematurely end if there’s more than one command (which it seems is what
>>> you’re seeing). Regardless of the reason, using a Context past the end
>>> of it’s lifetime is definitely asking for trouble.
>>>
>>> How to workaround this depends on the context. Can you give an example
>>> of the usage of your extension? Also, what thread is this event being
>>> triggered from?
>>>
>>> On Tue, Jan 7, 2020 at 4:23 PM TechnoRazor <therealte...@gmail.com>
>>> wrote:
>>>
>>>> My NetLogo extension has a command that binds an anonymous command to
>>>> an event. On the event, the command is called using:
>>>> command.perform(context, new Object[0]);
>>>> in which context is the context when the anonymous command was first
>>>> bound. This seemed to work fine until recently, when I noticed something
>>>> peculiar. The first time the event occurs after the command is bound, it
>>>> only runs the first command in the anonymous command. This poses a problem
>>>> for me, since, for example, if I bound the command "[-> if true [ print
>>>> true ]]" then it would never print "true" on the first call. I have no idea
>>>> why this is, does someone have an idea of why this happens and how to avoid
>>>> it? Thanks in advance.
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "netlogo-devel" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to netlog...@googlegroups.com.
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/d/msgid/netlogo-devel/de8251bd-4a06-4a2f-a936-edc7c55993e6%40googlegroups.com
>>>> <https://groups.google.com/d/msgid/netlogo-devel/de8251bd-4a06-4a2f-a936-edc7c55993e6%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>>
>>>
>>> --
>>> Bryan Head
>>> PhD Candidate, Computer Science
>>> Center for Connected Learning and Computer-Based Modeling
>>> Department of Electrical Engineering and Computer Science
>>> Northwestern University
>>>
>> --
> You received this message because you are subscribed to the Google Groups
> "netlogo-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to netlogo-devel+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/netlogo-devel/a7822a7b-b18c-4f62-af97-f9b2c0b4f0bd%40googlegroups.com
> <https://groups.google.com/d/msgid/netlogo-devel/a7822a7b-b18c-4f62-af97-f9b2c0b4f0bd%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>


-- 
Bryan Head
PhD Candidate, Computer Science
Center for Connected Learning and Computer-Based Modeling
Department of Electrical Engineering and Computer Science
Northwestern University

-- 
You received this message because you are subscribed to the Google Groups 
"netlogo-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netlogo-devel+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/netlogo-devel/CAFM%3DnTegNvJu%2B4seS1T-XxAVYhLbgiJDhijk9EZgfe%2B6x8DEcA%40mail.gmail.com.

Reply via email to