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
➜ Development
➜ Current plugin scoping
It is now over 60 days since the last post. This thread is closed.
Refresh page
Pages: 1 2
3
Posted by
| Twisol
USA (2,257 posts) Bio
|
Date
| Mon 13 Sep 2010 05:51 AM (UTC) Amended on Mon 13 Sep 2010 05:58 AM (UTC) by Twisol
|
Message
| So I was mulling over a few different things, and I remembered how I was talking to you, Nick, about making the current-plugin management cleaner. My suggestion at the time had exception safety issues. But today I think I have a solution that's much cleaner -and- has no exception safety issues. Here's the code:
class PluginScoper
{
public:
PluginScoper (CMUSHclientDoc* doc, CPlugin* plugin)
: _doc(doc)
{
_saved_plugin = _doc.m_CurrentPlugin;
_doc.m_CurrentPlugin = plugin;
}
~PluginScoper ()
{
_doc.m_CurrentPlugin = _saved_plugin;
}
private:
CMUSHclientDoc* _doc;
CPlugin* _saved_plugin;
};
Example:
{
PluginScoper pscope (doc, plugin);
// stuff here
// automatically reset here
}
If an exception occurs anywhere within the scope, the destructor is automatically called as the stack is unwound. Also, it's destructed automatically at the end of its scope anyways.
I'm not planning on using this just yet, but it seems to be a nice construct, and I'll definitely be putting it on my list of cleanup ideas. What are your thoughts? |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | Top |
|
Posted by
| Nick Gammon
Australia (23,046 posts) Bio
Forum Administrator |
Date
| Reply #1 on Mon 13 Sep 2010 06:22 AM (UTC) |
Message
| Yes that looks very sensible. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Twisol
USA (2,257 posts) Bio
|
Date
| Reply #2 on Mon 13 Sep 2010 06:23 AM (UTC) |
Message
| Thanks! |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | Top |
|
Posted by
| Nick Gammon
Australia (23,046 posts) Bio
Forum Administrator |
Date
| Reply #3 on Mon 13 Sep 2010 06:25 AM (UTC) |
Message
| My only reservation is that plugins are usually called in sequence (ie. not just a single plugin). But with some modification the general idea could be retained, but go through all plugins.
In fact, what is done a lot is to:
- Save the current plugin
- Loop through all plugins
- Ignore disabled plugins
- To non-disabled plugins, take some action
- Restore the saved plugin
All that could usefully be encapsulated. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Nick Gammon
Australia (23,046 posts) Bio
Forum Administrator |
Date
| Reply #4 on Mon 13 Sep 2010 06:27 AM (UTC) |
Message
| Maybe your idea could just be in the inner loop, with the slight overhead of the constructor/destructor calls. But maybe there is a slightly better way. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Twisol
USA (2,257 posts) Bio
|
Date
| Reply #5 on Mon 13 Sep 2010 06:34 AM (UTC) Amended on Mon 13 Sep 2010 06:35 AM (UTC) by Twisol
|
Message
| If you want the quick and dirty way, just do this:
{
PluginScoper pscope (m_pDoc, NULL);
// a code loop
{
m_pDoc->m_CurrentPlugin = foo;
}
// automatically reset here
}
I mean, I don't like it because you still directly affect the current plugin pointer, but it would work. I could add a new method to PluginScoper to let you indirectly affect the current plugin, but that would probably have un-obvious semantics when you have two of them in the same scope. |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | Top |
|
Posted by
| Nick Gammon
Australia (23,046 posts) Bio
Forum Administrator |
Date
| Reply #6 on Mon 13 Sep 2010 06:34 AM (UTC) |
Message
| You know, Twisol, if you really want to get into this you should read up on "function objects" in STL. For example:
http://gammon.com.au/forum/?id=4181
You could iterate through a list (ie. all plugins) applying a supplied function object to them (ie. the action you want to take). |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Nick Gammon
Australia (23,046 posts) Bio
Forum Administrator |
Date
| Reply #7 on Mon 13 Sep 2010 06:37 AM (UTC) |
Message
|
et. al. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Twisol
USA (2,257 posts) Bio
|
Date
| Reply #8 on Mon 13 Sep 2010 06:38 AM (UTC) |
Message
| Yep, functors. I've used them before, though not extensively. I wrote a set of input/output stream manipulators you could use with cin/cout to change the text color and cursel location in the console.
I admit that I'm not sure what an elegant solution would be using functors; I haven't used them enough to have a real feel for where they fit best. I'll mull it over. |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | Top |
|
Posted by
| Twisol
USA (2,257 posts) Bio
|
Date
| Reply #9 on Mon 13 Sep 2010 07:22 AM (UTC) Amended on Mon 13 Sep 2010 07:28 AM (UTC) by Twisol
|
Message
| Okay, I have another idea. Instead of using PluginScoper to both store and set the current plugin, just use it to store the current plugin. Then you manipulate the current plugin pointer how you normally would. It's kind of like an auto_ptr.
class CurrentPluginScoper
{
public:
CurrentPluginScoper (CMUSHclientDoc* doc)
: _doc(doc), _saved_plugin(doc.m_CurrentPlugin)
{}
~CurrentPluginScoper ()
{
_doc.m_CurrentPlugin = _saved_plugin;
}
private:
CMUSHclientDoc* _doc;
CPlugin* _saved_plugin;
};
{
CurrentPluginScoper pscope (m_pDoc);
// a code loop
{
m_pDoc->m_CurrentPlugin = foo;
}
// automatically reset here
}
The whole point here is to maintain the previous current plugin in an exception-safe way, and it has the desirable byproduct that it's cleaner, since you don't have to explicitly set it back. It still gives you full ownership of what the current plugin is, letting you do your plugin loops while maintaining previous context.
I just asked myself what the simplest thing that could possibly work would be, and this is what I got.
[EDIT] The name is dreadful; I'm open to suggestions. |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | Top |
|
Posted by
| Twisol
USA (2,257 posts) Bio
|
Date
| Reply #10 on Tue 14 Sep 2010 07:30 AM (UTC) Amended on Tue 14 Sep 2010 07:35 AM (UTC) by Twisol
|
Message
| By the way, I read that Lua uses setjmp and longjmp for error handling (and coroutines), so if you use lua_error() and it skips past one of these - or really, anything that has a destructor - it'll never be destructed. That's a very, very nice pitfall that seems really easy to fall for...
[EDIT]: *facepalm* Of course, the very next e-mail I read in the mailing list archives is by Nick. |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #11 on Tue 14 Sep 2010 03:48 PM (UTC) |
Message
|
Quote: CurrentPluginScoper
CurrentPluginContext? Python calls this sort of thing a 'context', although it also has more explicit syntax support. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Twisol
USA (2,257 posts) Bio
|
Date
| Reply #12 on Tue 14 Sep 2010 06:34 PM (UTC) |
Message
| I was thinking about that, but it's not really a context. Nothing changes unless you set the current plugin yourself, all this thing does is guarantee that it's set back.
CurrentPluginSaver? |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #13 on Tue 14 Sep 2010 06:40 PM (UTC) |
Message
| I would make it so that the scoped object takes care of setting and restoring, to be explicit. Is there a reason why you'd save it, set it later, and restore it upon destruction? Why not save+set on construction and restore on destruction? |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Twisol
USA (2,257 posts) Bio
|
Date
| Reply #14 on Tue 14 Sep 2010 06:59 PM (UTC) |
Message
| Because of the point Nick raised before, about how he loops over many plugins rather than just one. We could have a plugin scoper in the inner loop that's constructed/destructed every time, but frankly that's a bit disgusting. You could put the plugin scoper outside the loop and start it with NULL, but then you're circumventing the class.
I thought about it, and all we really need is a way to save and restore the current plugin. We can leave the actual current-plugin management to the user code. Of course, you can do this:
PluginScoper& operator= (CPlugin* plugin)
{
_doc->m_CurrentPlugin = plugin;
return *this;
}
Then you'd have something like this:
{
PluginScoper current_plugin(m_pDoc);
// some dummy loop here
while (true)
current_plugin = some_plugin;
}
Honestly, I just think the semantics could get confusing if you have multiple scopers in the same scope. But if that's something we can deal with easily, well okay then. |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | 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.
85,272 views.
This is page 1, subject is 3 pages long: 1 2
3
It is now over 60 days since the last post. This thread is closed.
Refresh page
top