ID:264456
 
Problem description:

I am wondering if there is a specific function that can be called to cause a verb to be executed without the user having to manually click the verb. If there is not an easy way of doing this, then please read on so that you can fully understand my dilemma.

I noticed an interesting difference between verbs and procs. When a proc is activated, the block of code within it must be fully executed before moving on to the following line of code (after the line at which the proc is called). Verbs, on the other hand, do not wait on other verbs or procs that are being executed at the time they're called. So, it would seem that verbs are multithreaded, whereas procs are not. Well, I am relying on this multithreading capability so that I can execute a particular verb multiple times without having to wait for the code block to be finished with its execution each time.

I have created a verb. When this verb is called, a proc is called beneath it. This proc takes about six seconds to be executed completely. I want the verb to automatically be executed before those six seconds elapse, and again, and so on and so forth. When the user clicks the verb, there is no delay - the code is executed immediately, regardless of whether or not the code is still pending the previous execution of the verb. I want for this to happen without the user having to click the verb. Alternatively, when I place multiple procs beneath the verb, each successive proc pends until the previous one has been executed completely. Please don't tell me to use procs (I know that procs can be executed automatically), unless you can provide a description of how to multithread them.
spawn()
You're very wrong there. DM is purely single-threaded, and also, at the technical level, verbs are barely any different from procs. Procs can even be used exactly like verbs by adding them to a verbs list, in fact the main difference between procs and verbs is that with verbs, the said adding is automatic.

Lethal Dragon wrote:
I am wondering if there is a specific function that can be called to cause a verb to be executed without the user having to manually click the verb.

Verbs can be called and executed exactly like procs can, in the same ways.

Also, let me explain Jp's mentioning of spawn(), which would be useful to you here: it can be used to schedule a block of code to run at a later time (after a delay, which can also be set to be small, or virtually nonexistent most of the time by setting it to -1 - look up sleep() too for more info), separately from the current proc (in pretty much a copy of it). This means the current proc doesn't need to necessarily wait for the code in the spawn() to finish, it can continue before it ends provided execution returns to it (remember, DM is still single-threaded and only one thing runs at a time).
In response to Kaioken (#2)
Alright... Perhaps there has been some sort of misinterpretation. For now, let's forget about what has previously been stated - I'll start fresh. Suppose you have a verb that, once executed, causes a bullet to be fired from the far West side to the East side of a large map. The bullet will obviously take some time to reach its destination from the time at which it was fired. Now, you could call this verb by finding it beneath the statpanel and clicking it. Or, like you mentioned, you could simply call it by using the same syntax required for calling procs. Now, I'm assuming, from what you stated in your response, that you believe that the final product would be the same for both methods. Well, I claim that the difference between the final products would depend on a certain condition; if the bullet were in the midst of its travelling from point A to point B, then the two methods would produce different results. Calling the verb manually, by clicking it, would fire another bullet, while the previously fired bullet would continue along its path. This is what I meant when I used the term, "multithreaded"; in this example, we have two bullets travelling simultaneously. Calling the verb automatically (using Fire(), or whatever) would not produce this same effect. If it would, and I'm wrong, please send me a simple example of code that proves this not to be the case.

That aside, I must thank you for expanding on the spawn() proc as a possible solution. I was indeed able to use this proc to solve the issue =). But, I would still like for you to explain to me how the above example is not accurate and/or is invalid. If you agree with it, then please tell me how it doesn't relate to my previous post.
In response to Lethal Dragon (#3)
Uhh..
spawn()
Fire()

//or even
spawn Fire()

Sorry, not understanding the Great Wall of Text there.
In response to Lethal Dragon (#3)
Calling BYOND "strictly single-threaded" is being a bit silly, because everything that doesn't use multiple processors is "strictly single-threaded". Parallelism in BYOND is basically achieved by having a queue of procs that are waiting for execution, and simply grabbing the one at the top whenever the current thread sleeps or ends. A thread, however, is not interrupted unless it is explicitly interrupted (or with the background setting which explicitly interrupts it after each iteration of a loop or somesuch).

Regardless, the effect is generally the same as if two segments of code were running at the same time, only without nasty race conditions.

The issue you're describing has nothing to do with how verbs or procs are called. What you have is something like this:

proc
shootbullets()
while(1)
var/obj/bullet/B = new(somewhere)
B.shoot()
sleep(50)

obj/bullet
proc/shoot()
while(step(src, dir))
sleep(10)
del(src)


You are expecting a bullet to shoot every 5 seconds. However, in actuality, shootbullets() is waiting for shoot() to finish, which is going to take however long it takes it to hit something. THEN, it will wait 5 seconds, and shoot a new bullet. It's all one thread.

However, by giving players a verb to press that creates a bullet and calls shoot(), each time they press the verb it has its own thread, so they will occur "in parallel", and nothing is waiting for the bullet to hit a wall (or rather: the verb is waiting, but won't do anything once it stops waiting).

spawn() allows you to explicitly create a new thread, which you'd use like so:

proc
shootbullets()
while(1)
var/obj/bullet/B = new(somewhere)
spawn() B.shoot()
sleep(50)


Then, (in all technicality): B.shoot() gets pushed onto the queue, sleep(50) is reached, the current thread gives up control until 5 seconds from now, and B.shoot() is processed in a separate thread once it's reached in the queue (which will be within one tick). This will result in a bullet being fired every 5 seconds.