Utils: Add ScopeExit class
g0dil [Fri, 16 Jan 2009 22:24:01 +0000 (22:24 +0000)]
Utils/Console: Add '@' to 'ls' output for link nodes
Utils/Console: Path completion in the LineEditor follows links in all cases
Utils/Console: Path completion adds blank space after non-directories

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1063 270642c3-0616-0410-b53a-bc976706d245

Scheduler/FIFORunner.cc
Scheduler/Scheduler.cc
Utils/Console/Executor.cc
Utils/Console/LineEditor.cc
Utils/Console/Node.cci
Utils/Console/Node.hh
Utils/Console/testServer.cc
Utils/ScopeExit.cci [new file with mode: 0644]
Utils/ScopeExit.hh [new file with mode: 0644]
Utils/Termlib/Editor.cc

index 545b4ae..b39b5c2 100644 (file)
 // Custom includes
 #include <signal.h>
 #include <time.h>
+#include <boost/lambda/lambda.hpp>
 #include "../Utils/Exception.hh"
 #include "../Utils/senfassert.hh"
+#include "../Utils/ScopeExit.hh"
 
 //#include "FIFORunner.mpp"
 #define prefix_
@@ -143,7 +145,6 @@ prefix_ void senf::scheduler::detail::FIFORunner::run()
     run(f, l);
 }
 
-
 prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, TaskList::iterator l)
 {
     if (f == l)
@@ -164,32 +165,30 @@ prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, Task
     tasks_.insert(l, null);
     TaskList::iterator end (TaskList::current(null));
     next_ = f;
-    try {
-        while (next_ != end) {
-            TaskInfo & task (*next_);
-            if (task.runnable_) {
-                task.runnable_ = false;
-                runningName_ = task.name();
-#           ifdef SENF_DEBUG
-                runningBacktrace_ = task.backtrace_;
-#           endif
-                TaskList::iterator i (next_);
-                ++ next_;
-                tasks_.splice(l, tasks_, i);
-                watchdogCount_ = 1;
-                task.run();
-            }
-            else
-                ++ next_;
+
+    using namespace boost::lambda;
+    ScopeExit atExit ((
+                          var(watchdogCount_) = 0, 
+                          var(next_) = l
+                          ));
+    
+    while (next_ != end) {
+        TaskInfo & task (*next_);
+        if (task.runnable_) {
+            task.runnable_ = false;
+            runningName_ = task.name();
+#       ifdef SENF_DEBUG
+            runningBacktrace_ = task.backtrace_;
+#       endif
+            TaskList::iterator i (next_);
+            ++ next_;
+            tasks_.splice(l, tasks_, i);
+            watchdogCount_ = 1;
+            task.run();
         }
+        else
+            ++ next_;
     }
-    catch (...) {
-        watchdogCount_ = 0;
-        next_ = l;
-        throw;
-    }
-    watchdogCount_ = 0;
-    next_ = l;
 }
 
 prefix_ senf::scheduler::detail::FIFORunner::TaskList::iterator
index e7550bb..2467459 100644 (file)
@@ -48,31 +48,40 @@ prefix_ void senf::scheduler::terminate()
     terminate_ = true;
 }
 
+namespace {
+    
+    // We don't want try { } catch(...) { ... throw; } since that will make debugging more
+    // difficult: the stack backtrace for an unexpected exception would always end here.
+    struct SchedulerScopedInit
+    {
+        SchedulerScopedInit() 
+            {
+                senf::scheduler::detail::FIFORunner::instance().startWatchdog();
+                senf::scheduler::detail::SignalDispatcher::instance().unblockSignals();
+                senf::scheduler::detail::TimerDispatcher::instance().unblockSignals();
+            }
+
+        ~SchedulerScopedInit()
+            {
+                senf::scheduler::detail::TimerDispatcher::instance().blockSignals();
+                senf::scheduler::detail::SignalDispatcher::instance().blockSignals();
+                senf::scheduler::detail::FIFORunner::instance().stopWatchdog();
+            }
+    };
+}
+
 prefix_ void senf::scheduler::process()
 {
-    try {
-        detail::FIFORunner::instance().startWatchdog();
-        detail::SignalDispatcher::instance().unblockSignals();
-        detail::TimerDispatcher::instance().unblockSignals();
-        terminate_ = false;
-        while(! terminate_ && ! (detail::FdDispatcher::instance().empty() &&
-                                 detail::TimerDispatcher::instance().empty() &&
-                                 detail::FileDispatcher::instance().empty())) {
-            detail::FdManager::instance().processOnce();
-            detail::FileDispatcher::instance().prepareRun();
-            detail::EventHookDispatcher::instance().prepareRun();
-            detail::FIFORunner::instance().run();
-        }
-    }
-    catch(...) {
-        detail::TimerDispatcher::instance().blockSignals();
-        detail::SignalDispatcher::instance().blockSignals();
-        detail::FIFORunner::instance().stopWatchdog();
-        throw;
+    SchedulerScopedInit initScheduler;
+    terminate_ = false;
+    while(! terminate_ && ! (detail::FdDispatcher::instance().empty() &&
+                             detail::TimerDispatcher::instance().empty() &&
+                             detail::FileDispatcher::instance().empty())) {
+        detail::FdManager::instance().processOnce();
+        detail::FileDispatcher::instance().prepareRun();
+        detail::EventHookDispatcher::instance().prepareRun();
+        detail::FIFORunner::instance().run();
     }
-    detail::TimerDispatcher::instance().blockSignals();
-    detail::SignalDispatcher::instance().blockSignals();
-    detail::FIFORunner::instance().stopWatchdog();
 }
 
 prefix_ void senf::scheduler::restart()
index f78a736..04cb751 100644 (file)
@@ -194,8 +194,10 @@ prefix_ void senf::console::Executor::ls(std::ostream & output,
     DirectoryNode::child_iterator const i_end (node.children().end());
     for (; i != i_end; ++i) {
         output << i->first;
-        if (boost::dynamic_pointer_cast<DirectoryNode>(i->second))
+        if (i->second->isDirectory())
             output << "/";
+        else if (i->second->isLink())
+            output << "@";
         output << "\n";
     }
 }
index bf4d869..31df1f7 100644 (file)
@@ -145,7 +145,7 @@ completePath(term::LineEditor & editor, unsigned b, unsigned e,
     if (path.empty()) {
         DirectoryNode::ChildrenRange cs (client().cwd().children());
         for (DirectoryNode::ChildrenRange::iterator i (cs.begin()); i != cs.end(); ++i)
-            completions.push_back(i->first + (i->second->isDirectory() ? "/" : ""));
+            completions.push_back(i->first + (i->second->followLink().isDirectory() ? "/" : " "));
         return;
     }
     
@@ -180,10 +180,10 @@ completePath(term::LineEditor & editor, unsigned b, unsigned e,
             else {
                 DirectoryNode::ChildrenRange cs (dir->completions(i->value()));
                 if (has_one_elt(cs)) {
-                    GenericNode * node (cs.begin()->second.get());
-                    if (!node->isDirectory())
+                    GenericNode & node (cs.begin()->second->followLink());
+                    if (!node.isDirectory())
                         return;
-                    dir = static_cast<DirectoryNode*>(node);
+                    dir = static_cast<DirectoryNode*>(&node);
                     basePath += cs.begin()->first + "/";
                 }
                 else
@@ -193,7 +193,8 @@ completePath(term::LineEditor & editor, unsigned b, unsigned e,
 
     DirectoryNode::ChildrenRange cs (dir->completions(i->value()));
     for (DirectoryNode::ChildrenRange::iterator j (cs.begin()); j != cs.end(); ++j)
-        completions.push_back(basePath + j->first + (j->second->isDirectory() ? "/" : ""));
+        completions.push_back(basePath + j->first 
+                              + (j->second->followLink().isDirectory() ? "/" : " "));
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index dabaec9..1c130cb 100644 (file)
@@ -114,6 +114,21 @@ prefix_ bool senf::console::GenericNode::isCommand()
     return dynamic_cast<CommandNode const *>(this);
 }
 
+prefix_ senf::console::GenericNode const & senf::console::GenericNode::followLink()
+    const
+{
+    return isLink()
+        ? dynamic_cast<LinkNode const *>(this)->follow()
+        : *this;
+}
+
+prefix_ senf::console::GenericNode & senf::console::GenericNode::followLink()
+{
+    return isLink()
+        ? dynamic_cast<LinkNode *>(this)->follow()
+        : *this;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::LinkNode
 
@@ -154,10 +169,7 @@ prefix_ senf::console::GenericNode &
 senf::console::DirectoryNode::get(std::string const & name)
     const
 {
-    GenericNode & node (getLink(name));
-    return node.isLink()
-        ? dynamic_cast<LinkNode&>(node).follow()
-        : node;
+    return getLink(name).followLink();
 }
 
 prefix_ senf::console::DirectoryNode &
index 137c8b0..6caef96 100644 (file)
@@ -296,6 +296,9 @@ namespace console {
         bool isLink() const;            ///< \c true, if this is a link node
         bool isCommand() const;         ///< \c true, if this is a command node
 
+        GenericNode const & followLink() const; ///< Follow link if \c this node is a link node
+        GenericNode & followLink();     ///< Follow link if \c this node is a link node
+
     protected:
         GenericNode();
 
@@ -491,7 +494,7 @@ namespace console {
                                         ///< \c true, if there is a child with name \a name
 
         GenericNode & get(std::string const & name) const;
-                                        ///< Get child node
+                                        ///< Get child node automatically dereferencing links
                                         /**< \throws UnknownNodeNameException if a child \a name
                                                  does not exist */
         GenericNode & getLink(std::string const & name) const;
@@ -500,7 +503,7 @@ namespace console {
                                                  does not exist */
 
         DirectoryNode & getDirectory(std::string const & name) const;
-                                        ///< Get directory child node
+                                        ///< Get directory child node (dereferencing links)
                                         /**< Same as operator[]
                                              \throws UnknownNodeNameException if a child \a name
                                                  does not exist.
@@ -508,7 +511,7 @@ namespace console {
                                                  directory node. */
 
         DirectoryNode & operator[](std::string const & name) const;
-                                        ///< Get directory child node
+                                        ///< Get directory child node (dereferencing links)
                                         /**< Same as getDirectory
                                              \throws UnknownNodeNameException if a child \a name
                                                  does not exist.
@@ -516,7 +519,7 @@ namespace console {
                                                  directory node. */
 
         CommandNode & getCommand(std::string const & name) const;
-                                        ///< Get command child node
+                                        ///< Get command child node (dereferencing links)
                                         /**< Same as operator()
                                              \throws UnknownNodeNameException if a child \a name
                                                  does not exist
@@ -524,7 +527,7 @@ namespace console {
                                                  command node. */
 
         CommandNode & operator()(std::string const & name) const;
-                                        ///< Get command child node
+                                        ///< Get command child node (dereferencing links)
                                         /**< Same as getCommand()
                                              \throws UnknownNodeNameException if a child \a name
                                                  does not exist
index 7458055..5d1a323 100644 (file)
@@ -97,6 +97,8 @@ int main(int, char **)
         .add("showlog", &enableLogging)
         .doc("Enable display of log messages on the current console");
 
+    senf::console::root().link("sl", senf::console::root()["console"]("showlog"));
+
     serverDir
         .add("shutdown", &shutdownServer)
         .doc("Terminate server application");
@@ -110,6 +112,8 @@ int main(int, char **)
         .add("extra", test.dir)
         .doc("Example of an instance directory");
 
+    senf::console::root().link("ex", test.dir);
+
     senf::console::Server::start( senf::INet4SocketAddress(23232u) )
         .name("testServer");
 
diff --git a/Utils/ScopeExit.cci b/Utils/ScopeExit.cci
new file mode 100644 (file)
index 0000000..09ff9cf
--- /dev/null
@@ -0,0 +1,54 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief ScopeExit inline non-template implementation */
+
+//#include "ScopeExit.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ senf::ScopeExit::ScopeExit(Function const & fn)
+    : fn_ (fn)
+{}
+
+prefix_ senf::ScopeExit::~ScopeExit()
+{
+    fn_();
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/ScopeExit.hh b/Utils/ScopeExit.hh
new file mode 100644 (file)
index 0000000..ee72622
--- /dev/null
@@ -0,0 +1,67 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief ScopeExit public header */
+
+#ifndef HH_SENF_Utils_ScopeExit_
+#define HH_SENF_Utils_ScopeExit_ 1
+
+// Custom includes
+#include <boost/function.hpp>
+#include <boost/utility.hpp>
+
+//#include "ScopeExit.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+
+    class ScopeExit : boost::noncopyable
+    {
+    public:
+        typedef boost::function<void ()> Function;
+
+        explicit ScopeExit(Function const & fn);
+        ~ScopeExit();
+
+    private:
+        Function fn_;
+    };
+
+}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "ScopeExit.cci"
+//#include "ScopeExit.ct"
+//#include "ScopeExit.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index 9fc6e68..f3a0c19 100644 (file)
@@ -276,7 +276,7 @@ prefix_ void senf::term::BaseEditor::write(std::string const & s)
 ///////////////////////////////////////////////////////////////////////////
 
 prefix_ senf::term::LineEditor::LineEditor(AbstractTerminal & terminal, AcceptCallback cb)
-    : BaseEditor(terminal), enabled_ (true), prompt_ ("$"), promptWidth_ (1u), editWidth_ (0u), 
+    : BaseEditor(terminal), enabled_ (false), prompt_ ("$"), promptWidth_ (1u), editWidth_ (0u), 
       text_ (""), point_ (0u), displayPos_ (0u), lastKey_ (0u), callback_ (cb), historyPoint_ (0u)
 {
     defineKey(KeyParser::Return,    &bindings::accept);
@@ -521,7 +521,7 @@ prefix_ bool senf::term::LineEditor::cb_init()
     if (!BaseEditor::cb_init())
         return false;
     prompt(prompt_);
-    forceRedisplay();
+    show();
     return true;
 }