Gammon Forum
Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Entire forum
MUSHclient
Tips and tricks
PPI - A plugin communications script
PPI - A plugin communications script
|
It is now over 60 days since the last post. This thread is closed.
  Refresh page
Pages: 1
2
3 4
5
6
7
8
9
10
Posted by
| Nick Gammon
Australia (23,043 posts) bio
Forum Administrator |
Date
| Reply #30 on Sat 09 Jan 2010 10:41 PM (UTC) |
Message
| By the way, there is a potential for a subtle problem. People *can* do this, although they are probably ill-advised to:
Now everything still works fine ... except anything that explicitly refers to _G (as yours and my code does). You can work around it like this:
local _G = getfenv ()
-- hide all except non-local variables
module (..., package.seeall)
Now we have a local copy of _G which is getfenv () (which is what _G really is anyway). Now it doesn't matter if the caller has mucked around with _G or not.
I must admit that some of the issues raised by the Lua group are valid (although they can nitpick at times). |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Twisol
USA (2,257 posts) bio
|
Date
| Reply #31 on Mon 11 Jan 2010 08:40 PM (UTC) Amended on Mon 11 Jan 2010 10:10 PM (UTC) by Twisol
|
Message
| After a few days hard work, I finally implemented function-passing/returning, and Exporting of non-function values. For all intents and purposes, I think this is functionally complete. Linked below is the paste for PPI v1.2.0. [1]
Nick, I'd appreciate it if you could comment out the two lines on 307 and 308 to test the nonce-checking in version 4.46. It's supposed to store the nonce when the PPI is reloaded, and if it's changed, all thunks that refer to the other plugin will fail to execute (because there's no guarantee the same IDs refer to the same functions). So if the nonce -hasn't- changed, then reloaded should be false (the two commented-out lines), so the plugin knows not to send initialization stuff again.
Some testing of the new features with the below service seem to work very well:
PPI.Expose("n_test", 42)
PPI.Expose("s_test", "blue")
PPI.Expose("b_test", true)
PPI.Expose("z_test", nil)
PPI.Expose("t_test", {
"test",
42,
true,
nil,
function()
print("test from ATCP")
return {true, 42}
end,
})
Expected use of the nonce-checking in client code:
OnPluginListChanged = function()
local atcp, reloaded = PPI.Load("7c08e2961c5e20e5bdbf7fc5")
if not atcp then
error("ATCP plugin not installed. Please install the ATCP plugin, then reinstall this plugin.")
elseif reloaded then
atcp.EnableModule("room_brief")
_G["atcp"] = atcp
end
end
[1] http://mushclient.pastebin.com/f1964fd71 see below post. |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | top |
|
Posted by
| Twisol
USA (2,257 posts) bio
|
Date
| Reply #32 on Mon 11 Jan 2010 10:10 PM (UTC) Amended on Mon 11 Jan 2010 10:30 PM (UTC) by Twisol
|
Message
| Just added a one-liner bugfix, as I realized that deserialize() would keep returning the outdated thunk if the other plugin had been reinstalled. Just added 'tbl.thunks = {}' to the Load function under tbl.nonce.
Also, being an idiot, the link I pasted in the above post goes to the wrong paste. I've removed that paste because I didn't even intend to paste it at all.
EDIT: Also, I'd like to point out that running an admittedly lightweight method across PPI 10,000 times takes only ~6.15 seconds. That's a paltry ~0.615 miliseconds (less than one ms) per call on average.
Granted, the same loop on the equivalent implementation within the same plugin space takes only 11 miliseconds to execute all 10,000 calls, but I don't think anyone really expected PPI to be quite that speedy.
local tstart = GetInfo(232)
for i=1,10000 do
atcp.EnableModule('room_brief')
end
print(GetInfo(232) - tstart)
EDIT 2: By caching the indexing call as below, it cuts execution time using the PPI down to ~2.86 seconds for 10,000 calls, because it doesn't have to do a costly lookup every time. This follows the same logic as setting globals to locals before intensive loops in normal Lua, so it's not terribly unexpected either.
local tstart = GetInfo(232)
local EnableModule = atcp.EnableModule
for i=1,10000 do
EnableModule('room_brief')
end
print(GetInfo(232) - tstart)
[1] v1.2.1: http://mushclient.pastebin.com/f6d7cd307 |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | top |
|
Posted by
| Nick Gammon
Australia (23,043 posts) bio
Forum Administrator |
Date
| Reply #33 on Tue 12 Jan 2010 12:19 AM (UTC) |
Message
| Just out of interest on the timing, and I agree it probably doesn't matter unless you are calling functions *a lot*, my earlier version is about 4 times as fast. Probably because it is setting up less variables than yours.
Doing 2 tests in succession, from your version I got:
Time taken = 4.364 seconds (test 1)
Time taken = 5.216 seconds (test 2)
From my version, calling the same functions:
Time taken = 1.137 seconds (test 1)
Time taken = 1.168 seconds (test 2)
My test code sent 2 arguments, and got 2 results:
-- client
for i = 1, 10000 do
my_service.SomeMethodHere (42, "Nick")
end -- for
-- service
function SomeMethodHere (...)
return 1, 2
end
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Twisol
USA (2,257 posts) bio
|
Date
| Reply #34 on Tue 12 Jan 2010 12:44 AM (UTC) Amended on Tue 12 Jan 2010 01:04 AM (UTC) by Twisol
|
Message
| It could also be that I'm doing extra CallPlugin()s and serializations for the PPI_ACCESS message, because I support more than just methods. I would imagine that would slow it down a bit. Caching the index result as a local and calling that sped my test up to ~2.86 seconds on average, which is much closer to your total. Your version also doesn't support nested tables, which I imagine would also speed things up.
EDIT: I forgot to rename PPI_SUPPORTS to PPI_ACCESS in the message IDs section at the top. Well, re-pasted and version number updated (1.2.2)...
[1] PPI v1.2.2: http://mushclient.pastebin.com/f2cbbca69 |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | top |
|
Posted by
| Nick Gammon
Australia (23,043 posts) bio
Forum Administrator |
Date
| Reply #35 on Tue 12 Jan 2010 01:30 AM (UTC) |
Message
|
Twisol said:
Your version also doesn't support nested tables, which I imagine would also speed things up.
Mine supports nested tables, just not tables that are self-referential or refer to other tables. For simple data passing (like passing a table of styles) that should be fine. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Twisol
USA (2,257 posts) bio
|
Date
| Reply #36 on Tue 12 Jan 2010 01:38 AM (UTC) Amended on Tue 12 Jan 2010 01:40 AM (UTC) by Twisol
|
Message
| Aren't tables that refer to other tables the same as tables within tables? I'm confused.
Testing with 'print(serialize.save_simple({1, 2, 3, {4, 5}}))' does indeed work, so I guess I just don't understand what you meant. Though, the fact that I support self-referential tables via a cache might add overhead.
I do notice that if save_simple comes across the same table twice, it treats them as separate tables, so on deserialization they will be separate objects. That's a problem my implementation does solve.
EDIT: Interesting, the non-_simple version of save does support self-referential tables, and tables that appear multiple times. Its output reminds me of an SQL dump. But ignore me, I'm just experimenting here. |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | top |
|
Posted by
| Nick Gammon
Australia (23,043 posts) bio
Forum Administrator |
Date
| Reply #37 on Tue 12 Jan 2010 02:13 AM (UTC) |
Message
| Referring to other tables:
t1 = { 1, 2, 3, 4, 5 }
t2 = { 6, 7, t1 }
In that example, t2 refers to another table (t1). Thus t2 can't be simply serialized because you also need to serialize t1.
And this is self-reference:
So t1, index 1, contains a reference to itself.
However tables within tables are OK:
t1 = {
wolf = { hp = 42, mana = 0 },
naga = { hp = 100, mana = 10 }
}
That is a simple nested table. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Twisol
USA (2,257 posts) bio
|
Date
| Reply #38 on Tue 12 Jan 2010 02:25 AM (UTC) Amended on Tue 12 Jan 2010 02:26 AM (UTC) by Twisol
|
Message
| Well, this:
t1 = {
wolf = { hp = 42, mana = 0 },
naga = { hp = 100, mana = 10 }
}
is precisely the same internally as this:
twolf = {hp = 42, mana = 0}
tnaga = {hp = 100, mana = 10}
t1 = {wolf = twolf, naga = tnaga}
Tables are like pointers, and other values are like normal values. It doesn't matter how you place the table pointers, because in the end they turn out the same.
Self-reference is of course the same internally, but we both know how differently it needs to be handled, since you can go into an infinite loop.
EDIT: Using serialize.save_simple(t1) on the second code snippet above gives the same output, i.e. this:
{
naga = {
hp = 100,
mana = 10,
},
wolf = {
hp = 42,
mana = 0,
},
}
|
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | top |
|
Posted by
| Nick Gammon
Australia (23,043 posts) bio
Forum Administrator |
Date
| Reply #39 on Tue 12 Jan 2010 05:33 AM (UTC) Amended on Tue 12 Jan 2010 05:34 AM (UTC) by Nick Gammon
|
Message
|
Twisol said:
Well, this:
t1 = {
wolf = { hp = 42, mana = 0 },
naga = { hp = 100, mana = 10 }
}
is precisely the same internally as this:
twolf = {hp = 42, mana = 0}
tnaga = {hp = 100, mana = 10}
t1 = {wolf = twolf, naga = tnaga}
Tables are like pointers, and other values are like normal values. It doesn't matter how you place the table pointers, because in the end they turn out the same.
Well, not precisely.
Your second snippet puts two tables into global namespace, mine doesn't. I know tables are like pointers, but your second example makes two additional tables globally available. It makes a difference.
eg.
_G ["twolf"] = {hp = 42, mana = 0}
_G ["tnaga"] = {hp = 100, mana = 10}
t1 = {wolf = twolf, naga = tnaga}
See? Your example make additional variables available to be accessed or modified without reference to t1. In my example, t1 "owns" the other tables.
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Twisol
USA (2,257 posts) bio
|
Date
| Reply #40 on Tue 12 Jan 2010 05:38 AM (UTC) Amended on Tue 12 Jan 2010 05:40 AM (UTC) by Twisol
|
Message
| Well, sure. The point was that there's no difference in the tables themselves after all's said and done. I could have been pedantic and done this:
local twolf = {hp = 42, mana = 0}
local tnaga = {hp = 100, mana = 10}
t1 = {wolf = twolf, naga = tnaga}
twolf = nil
tnaga = nil
If it is said that a table contains another table, it's considered to be exactly the same as a table with a value that refers to another table, regardless of what's going on with external pointers to either of the two tables.
EDIT in response to:
Nick Gammon said: Your second snippet puts two tables into global namespace, mine doesn't. I know tables are like pointers, but your second example makes two additional tables globally available. It makes a difference.
They're not additional tables if they exist regardless. The only extra 'things' involved are references to said tables.
I do find it a little funny (in a good way) that we're debating the exact interpretation of the composition of tables in this thread. *laughs* |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | top |
|
Posted by
| Nick Gammon
Australia (23,043 posts) bio
Forum Administrator |
Date
| Reply #41 on Tue 12 Jan 2010 05:43 AM (UTC) |
Message
|
Twisol said:
They're not additional tables if they exist regardless. The only extra 'things' involved are references to said tables.
My wording was "your second example makes two additional tables globally available". That's what it does. It adds two tables to global namespace. I don't debate that the two tables exist. I am saying that the difference is you have constructed three things in global namespace (the _G table if you like), whereas the earlier example constructed one thing in global namespace.
Your amended example using "local" has no extra impact on global namespace, granted, but I was working from your first example.
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Nick Gammon
Australia (23,043 posts) bio
Forum Administrator |
Date
| Reply #42 on Tue 12 Jan 2010 05:45 AM (UTC) |
Message
| I think the serialize.save_simple will serialize both examples correctly, however the serialize.save will correctly handle the case where both of the "extra" tables happen to be the same table. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Nick Gammon
Australia (23,043 posts) bio
Forum Administrator |
Date
| Reply #43 on Tue 12 Jan 2010 05:48 AM (UTC) |
Message
| If I may say, I think that a system that handles serializing parameters involving tables that refer to themselves, or refer to other tables outside the main table, are unlikely to be required in any sort of reasonable API that plugins that might expose.
You may be solving a problem that doesn't exist, and indeed, that we should not encourage to come into existence. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Nick Gammon
Australia (23,043 posts) bio
Forum Administrator |
Date
| Reply #44 on Tue 12 Jan 2010 05:50 AM (UTC) |
Message
|
Twisol said:
I do find it a little funny (in a good way) that we're debating the exact interpretation of the composition of tables in this thread. *laughs*
Indeed. Lua is incredibly powerful, and it is good to understand the underlying mechanisms, particularly if you are involved in generic parameter-passing.
Thankfully, most of the time it is very simple to use. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).
To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.
304,243 views.
This is page 3, subject is 10 pages long:
1
2
3 4
5
6
7
8
9
10
It is now over 60 days since the last post. This thread is closed.
  Refresh page
top
Quick links:
MUSHclient.
MUSHclient help.
Forum shortcuts.
Posting templates.
Lua modules.
Lua documentation.
Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.