SlideShare a Scribd company logo
1 of 63
Add an interactive command
line to your applications
Daniele Pallastrelli, daniele77.github.io
13.01.2022, Italian C++
My typical projects
• Run for a long period of time
• No classic interaction with the user (i.e., no GUI)
• Run in a server, custom board, almost never desktop applications
• They're not CPU bound applications
Why an interactive console in your apps?
• Need to have some sort of console to interact with my
applications (e.g., embedded systems running around the clock)
to:
• monitor,
• configure,
• manage the system
• E.g., CISCO routers
• Traditional systems: SSH connections + logs
Why an interactive console in your apps?
• Debugging
• Poke around internal state
• Dump internal structures
• Change the log level at runtime
• Change the working mode
• Enable / disable modules
• Load / unload plugins
• Early stage of development
Reinventing the wheel?
Existing solutions in open source domain:
• Linux only
• They're applications where you hook external programs to commands
• No remote sessions
• Few in C++
• None of them in "modern" C++
Enter the shell (cli?)
• My own library in C++14
• Production code quality
• Used in several industrial projects
• Demo time 
• C++14
• Cross-platform (Linux and windows tested)
• Menus and submenus
• Command history (navigation with arrow keys)
• Autocompletion (with TAB key)
• Async interface
• Colors
Something missing…
• Good when you start the app from a console (e.g. desktop
applications or development stage)
• What about processes that run in background (e.g., embedded,
servers & c)?
Try #1
Try #1
Try #2
Features summary
• C++14
• Header only
• Cross-platform (linux and windows)
• Menus and submenus
• Remote sessions (telnet)
• Persistent history (navigation with arrow keys)
• Autocompletion (with TAB key)
• Async interface
• Colors
auto rootMenu = make_unique<Menu>("cli");
rootMenu->Insert(
"hello",
[](std::ostream& out){ out << "Hello, worldn"; },
"Print hello world" );
rootMenu->Insert(
"hello_everysession",
[](std::ostream&){ Cli::cout() << "Hello, everybody" << std::endl; },
"Print hello everybody on all open sessions" );
rootMenu->Insert(
"reverse", {"string_to_revert"},
[](std::ostream& out, const string& arg)
{
string copy(arg);
std::reverse(copy.begin(), copy.end());
out << copy << "n";
},
"Print the reverse string" );
rootMenu->Insert(
"add", {"first_term", "second_term"},
[](std::ostream& out, int x, int y)
{
out << x << " + " << y << " = " << (x+y) << "n";
},
"Print the sum of the two numbers" );
rootMenu->Insert(
"sort", {"list of strings separated by space"},
[](std::ostream& out, std::vector<std::string> data)
{
std::sort(data.begin(), data.end());
out << "sorted list: ";
std::copy(data.begin(), data.end(), std::ostream_iterator<std::string>(out, " "));
out << "n";
},
"Alphabetically sort a list of words" );
auto subMenu = make_unique<Menu>("sub");
subMenu->Insert(
"demo",
[](std::ostream& out){ out << "This is a sample!n"; },
"Print a demo string" );
rootMenu->Insert( std::move(subMenu) );
// create a cli with the given root menu and a persistent storage
Cli cli( std::move(rootMenu), std::make_unique<FileHistoryStorage>(".cli") );
// global exit action
cli.ExitAction( [](auto& out){ out << "Goodbye and thanks for all the fish.n"; } );
// std exception custom handler
cli.StdExceptionHandler(
[](std::ostream& out, const std::string& cmd, const std::exception& e)
{
out << "Exception caught in cli handler: "
<< e.what()
<< " handling command: "
<< cmd
<< ".n";
}
);
LoopScheduler scheduler;
CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200);
localSession.ExitAction(
[&scheduler](auto& out) // session exit action
{
out << "Closing App...n";
scheduler.Stop();
}
);
scheduler.Run();
StandaloneAsioScheduler scheduler;
CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200);
localSession.ExitAction(
[&scheduler](auto& out) // session exit action
{
out << "Closing App...n";
scheduler.Stop();
}
);
// setup server
StandaloneAsioCliTelnetServer server(cli, scheduler, 5000);
// exit action for all the connections
server.ExitAction( [](auto& out) { out << "Terminating this session...n"; } );
scheduler.Run();
How does it work
Core idea
• Command list
• The user enters a string: command and parameters
• Iteration over the command list:
• Command name
• Parameter number and type
• The handler is called with the typed parameters
cli
hello hello_everysession sub
hello
demo
cli
hello
hello_everysession
sub
hello
demo
class Command {};
class Menu : public Command
{
private:
Menu* parent{ nullptr };
std::vector<Command*> cmds;
};
template <typename F, typename ... Args>
class VariadicFunctionCommand : public Command {};
Menu is-a Command, because when you start the CLI, every Menu shows as a command
you can digit at the prompt (e.g., if you define a Menu "foo", you get the command "foo" in
the Cli to enter the submenu).
auto rootMenu = make_unique<Menu>("cli");
rootMenu->Insert(
"hello",
[](std::ostream& out)
{
out << "Hello, worldn";
}
);
rootMenu->Insert(
"hello_everysession",
[](std::ostream&)
{
Cli::cout() << "Hello, everybodyn";
}
);
auto subMenu = make_unique<Menu>("sub");
subMenu->Insert(
"hello",
[](std::ostream& out)
{
out << "Hello, submenu worldn";
}
);
subMenu->Insert(
"demo",
[](std::ostream&)
{
out << "Demon";
}
);
rootMenu->Insert( std::move(subMenu) );
auto rootMenu = make_unique<Menu>("cli");
...
Cli cli( std::move(rootMenu) );
auto rootMenu = make_unique<Menu>("cli");
...
Cli cli( std::move(rootMenu) );
CliLocalTerminalSession localSession(cli,
scheduler, std::cout, 200);
CliTelnetServer server(cli, scheduler, 5000);
Cli cli( std::move(rootMenu) );
CliLocalTerminalSession localSession(cli,
scheduler, std::cout, 200);
CliTelnetServer server(cli, scheduler, 5000);
CliFileSession fileSession(cli, infile, outfile);
CliLocalTerminalSession localSession(
scheduler, std::cout, 200);
CliTelnetServer server(scheduler, 5000);
CliFileSession fileSession(infile, outfile);
Cli cli( std::move(rootMenu) );
cli.SetLocalSession( localSession );
cli.SetFileSession( fileSession );
cli.SetTelnetServer( server );
rootMenu->Insert(
"add", {"first_term", "second_term"},
[](std::ostream& out, int x, int y)
{
out << x << " + " << y << " = " << (x+y) << "n";
},
"Print the sum of two numbers"
);
rootMenu->Insert(
"add", {"first_term", "second_term"},
[](std::ostream& out, int x, int y)
{
out << x << " + " << y << " = " << (x+y) << "n";
},
"Print the sum of two numbers"
);
Interlude – How do you get the type of a
lambda argument?
template <typename F>
void foo(F f)
{
// what's the type of "f" first parameter?
// something like:
// using T = F::first_parameter_type
)
foo( [](int){} );
Interlude – How do you get the type of a
lambda argument?
template<typename F, typename Ret, typename A, typename... Rest>
A helper(Ret (F::*)(A, Rest...) const);
template <typename F>
void foo(F f)
{
using T = decltype( helper(&F::operator()) );
}
foo( [](int){} );
class Menu : public Command
{
public:
template <typename F>
CmdHandler Insert(const string& cmdName, F f)
{
return CreateCmd(cmdName, f, &F::operator());
}
private:
template <typename F, typename R, typename ... Args>
CmdHandler CreateCmd(const string& cmdName, F& f, R (F::*)(Args...) const)
{
auto cmd = make_unique< VariadicFunctionCommand< F, Args ... > >(cmdName, f);
// insert cmd into this menu commands
...
}
};
Works with lambdas
and std::function
class Menu : public Command
{
public:
...
template <typename R, typename ... Args>
CmdHandler Insert(const std::string& cmdName, R (*f)(Args...))
{
using F = R (*)(Args...);
auto cmd = make_unique<VariadicFunctionCommand<F, Args ...>>(cmdName, f);
// insert cmd into this menu commands
...
}
...
};
Overload for free-
functions
template <typename F, typename ... Args>
class VariadicFunctionCommand : public Command
{
public:
VariadicFunctionCommand(const std::string& _name, F fun) :
Command(_name), func(std::move(fun))
{}
bool Exec(const vector<string>& cmdLine) override
{
...
try
{
Select<Args...>::Exec(func, std::next(cmdLine.begin()), cmdLine.end());
}
catch (std::bad_cast&)
{
return false;
}
return true;
...
}
};
template <typename ... Args>
struct Select;
template <typename P, typename ... Args>
struct Select<P, Args...>
{
template <typename F, typename InputIt>
static void Exec(const F& f, InputIt first, InputIt last)
{
assert( first != last );
assert( std::distance(first, last) == 1+sizeof...(Args) );
const P firstPar = detail::from_string<typename std::decay<P>::type>(*first);
auto g = [&](auto ... pars){ f(firstPar, pars...); };
Select<Args...>::Exec(g, std::next(first), last);
}
};
template <>
struct Select<>
{
template <typename F, typename InputIt>
static void Exec(const F& f, InputIt first, InputIt last)
{
assert(first == last);
f();
}
};
Interlude
How do you manage concurrency?
Concurrency in my projects
• Single thread (when possible), using Proactor pattern.
• When I must: multiple threads, using Proactor pattern 
By the way…
…what's the PROACTOR pattern?
The proactor pattern: Concurrency Without Threads
The Proactor solution
Split every application service into:
• Long-duration operations. execute asynchronously
• Completion handlers. processes the results of the associated
asynchronous operations (potentially invoking additional
asynchronous operations).
Waiting for
completion events
Unblocking
Concurrency in my projects
• asio for asynchonous I/O (timers, too)
• asio::io_context available
• When I/O is ready, asio puts handler in the asio::io_context
• If more threads are needed (e.g., time consuming computations or
blocking I/O), the result is put in asio::io_context
• => everything runs in (my) single thread of execution
Back to the library 
• Input coming from:
• Keyboard, using blocking primitives (std::getchar() and _getch())
• Sockets
• Commands callbacks (in which thread?)
• => proactor (asio::io_context)
Consequences
• The user must instantiate a boost::asio::io_context object
• The whole library depends on boost::asio
Concurrency summary (v. 1.0)
• The library depends on boost::asio, even when you don't need the
telnet server
• Library users ask to use standalone asio instead of boost::asio
• The truth is that the whole library depends on boost::asio because:
• Telnet server needs it
• Keyboard handler needs an event handler
• The two must use the same event manager, i.e. boost::asio::io_context
Release 2.0 – Goals:
• Optionally use standalone asio instead of boost::asio for the telnet
server
• Remove all dependencies if the telnet server is not needed
Release 2.0 – The solution
• New abstraction: "Scheduler"
• schedules async event
• The library provides three kind of schedulers:
• StandaloneAsioScheduler (based on asio::io_context)
• BoostAsioScheduler (based on boost::asio::io_context)
• LoopScheduler (hand made sync queue)
Release 2.0 – The solution
• Cli library can use all the schedulers, but if you need the telnet server
you must use *AsioScheduler
• Bottom line:
• If ( you need telnet server OR your app already uses [boost::]asio::io_context
=> StandaloneAsioScheduler or BoostAsioScheduler
• Else
=> LoopScheduler (no external dependencies)
Release 2.0 – Standalone Asio
#include <cli/standaloneasioscheduler.h>
#include <cli/standaloneasioremotecli.h>
...
StandaloneAsioScheduler scheduler;
// setup local session
CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200);
// setup server
StandaloneAsioCliTelnetServer server(cli, scheduler, 5000);
// start event loop
scheduler.Run();
Release 2.0 – Boost Asio
#include <cli/boostasioscheduler.h>
#include <cli/boostasioremotecli.h>
...
BoostAsioScheduler scheduler;
// setup local session
CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200);
// setup server
BoostAsioCliTelnetServer server(cli, scheduler, 5000);
// start event loop
scheduler.Run();
Release 2.0 – No Asio
#include <cli/loopscheduler.h>
...
LoopScheduler scheduler;
// setup local session
CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200);
// start event loop
scheduler.Run();
Conclusions
Miles to go…
• User-defined arguments (and completion for them)
• More (bash-like) shortcuts
• Conan support
• Rename the library (?)
Library core: design decisions
• Reflection (?)
• Preprocessors (???)
• "Composite" Design Pattern VS Template metaprogramming
Intentional architecture VS emergent design
"Many times, thinking things out in advance saved us serious development headaches later on. ... [on
making a particular specification change] ... Making this change in the spec took an hour or two. If we
had made this change in code, it would have added weeks to the schedule. I can’t tell you how
strongly I believe in Big Design Up Front, which the proponents of Extreme Programming consider
anathema. I have consistently saved time and made better products by using BDUF and I’m proud to
use it, no matter what the XP fanatics claim. They’re just wrong on this point and I can’t be any clearer
than that."
-- Joel Spolsky "The project Aardwark Spec" – Joel On Software
Take away
• Use the right technique
• Use Cli library  (when you need it)
• Use Proactor pattern (when you need it)
• Use your brain (always)
References
Me: daniele.pallastrelli@gmail.com
Me: @DPallastrelli
Github: http://github.com/daniele77
Web: daniele77.github.io
63

More Related Content

What's hot

Berkeley Packet Filters
Berkeley Packet FiltersBerkeley Packet Filters
Berkeley Packet FiltersKernel TLV
 
Unbreakable VPN using Vyatta/VyOS - HOW TO -
Unbreakable VPN using Vyatta/VyOS - HOW TO -Unbreakable VPN using Vyatta/VyOS - HOW TO -
Unbreakable VPN using Vyatta/VyOS - HOW TO -Naoto MATSUMOTO
 
Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...Adrian Huang
 
Event driven workloads on Kubernetes with KEDA
Event driven workloads on Kubernetes with KEDAEvent driven workloads on Kubernetes with KEDA
Event driven workloads on Kubernetes with KEDANilesh Gule
 
Rust: Unlocking Systems Programming
Rust: Unlocking Systems ProgrammingRust: Unlocking Systems Programming
Rust: Unlocking Systems ProgrammingC4Media
 
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解するそうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解するshigeki_ohtsu
 
Linux Performance Profiling and Monitoring
Linux Performance Profiling and MonitoringLinux Performance Profiling and Monitoring
Linux Performance Profiling and MonitoringGeorg Schönberger
 
EBPF and Linux Networking
EBPF and Linux NetworkingEBPF and Linux Networking
EBPF and Linux NetworkingPLUMgrid
 
Kernel debug log and console on openSUSE
Kernel debug log and console on openSUSEKernel debug log and console on openSUSE
Kernel debug log and console on openSUSESUSE Labs Taipei
 
CICD using jenkins and Nomad
CICD using jenkins and NomadCICD using jenkins and Nomad
CICD using jenkins and NomadBram Vogelaar
 
Performance Wins with eBPF: Getting Started (2021)
Performance Wins with eBPF: Getting Started (2021)Performance Wins with eBPF: Getting Started (2021)
Performance Wins with eBPF: Getting Started (2021)Brendan Gregg
 
Writing Reusable Web Components with jQuery and jQuery UI
Writing Reusable Web Components with jQuery and jQuery UIWriting Reusable Web Components with jQuery and jQuery UI
Writing Reusable Web Components with jQuery and jQuery UIYnon Perek
 
Bash shell
Bash shellBash shell
Bash shellxylas121
 
Flux and InfluxDB 2.0 by Paul Dix
Flux and InfluxDB 2.0 by Paul DixFlux and InfluxDB 2.0 by Paul Dix
Flux and InfluxDB 2.0 by Paul DixInfluxData
 
Everything you always wanted to know about Redis but were afraid to ask
Everything you always wanted to know about Redis but were afraid to askEverything you always wanted to know about Redis but were afraid to ask
Everything you always wanted to know about Redis but were afraid to askCarlos Abalde
 

What's hot (20)

Berkeley Packet Filters
Berkeley Packet FiltersBerkeley Packet Filters
Berkeley Packet Filters
 
Unbreakable VPN using Vyatta/VyOS - HOW TO -
Unbreakable VPN using Vyatta/VyOS - HOW TO -Unbreakable VPN using Vyatta/VyOS - HOW TO -
Unbreakable VPN using Vyatta/VyOS - HOW TO -
 
Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...
 
Event driven workloads on Kubernetes with KEDA
Event driven workloads on Kubernetes with KEDAEvent driven workloads on Kubernetes with KEDA
Event driven workloads on Kubernetes with KEDA
 
Rust: Unlocking Systems Programming
Rust: Unlocking Systems ProgrammingRust: Unlocking Systems Programming
Rust: Unlocking Systems Programming
 
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解するそうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
 
Linux Performance Profiling and Monitoring
Linux Performance Profiling and MonitoringLinux Performance Profiling and Monitoring
Linux Performance Profiling and Monitoring
 
Using Netconf/Yang with OpenDalight
Using Netconf/Yang with OpenDalightUsing Netconf/Yang with OpenDalight
Using Netconf/Yang with OpenDalight
 
EBPF and Linux Networking
EBPF and Linux NetworkingEBPF and Linux Networking
EBPF and Linux Networking
 
Kernel debug log and console on openSUSE
Kernel debug log and console on openSUSEKernel debug log and console on openSUSE
Kernel debug log and console on openSUSE
 
CICD using jenkins and Nomad
CICD using jenkins and NomadCICD using jenkins and Nomad
CICD using jenkins and Nomad
 
Performance Wins with eBPF: Getting Started (2021)
Performance Wins with eBPF: Getting Started (2021)Performance Wins with eBPF: Getting Started (2021)
Performance Wins with eBPF: Getting Started (2021)
 
Shell Scripting
Shell ScriptingShell Scripting
Shell Scripting
 
Writing Reusable Web Components with jQuery and jQuery UI
Writing Reusable Web Components with jQuery and jQuery UIWriting Reusable Web Components with jQuery and jQuery UI
Writing Reusable Web Components with jQuery and jQuery UI
 
Bash shell
Bash shellBash shell
Bash shell
 
Unix signals
Unix signalsUnix signals
Unix signals
 
Flux and InfluxDB 2.0 by Paul Dix
Flux and InfluxDB 2.0 by Paul DixFlux and InfluxDB 2.0 by Paul Dix
Flux and InfluxDB 2.0 by Paul Dix
 
Everything you always wanted to know about Redis but were afraid to ask
Everything you always wanted to know about Redis but were afraid to askEverything you always wanted to know about Redis but were afraid to ask
Everything you always wanted to know about Redis but were afraid to ask
 
Making Linux do Hard Real-time
Making Linux do Hard Real-timeMaking Linux do Hard Real-time
Making Linux do Hard Real-time
 
eBPF/XDP
eBPF/XDP eBPF/XDP
eBPF/XDP
 

Similar to Add an interactive command line to your C++ application

2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloading2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloadingkinan keshkeh
 
Getting started cpp full
Getting started cpp   fullGetting started cpp   full
Getting started cpp fullVõ Hòa
 
Hands on Session on Python
Hands on Session on PythonHands on Session on Python
Hands on Session on PythonSumit Raj
 
Modern C++ Concurrency API
Modern C++ Concurrency APIModern C++ Concurrency API
Modern C++ Concurrency APISeok-joon Yun
 
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbsSystem Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbsashukiller7
 
Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Yandex
 
Developer Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duoDeveloper Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duoThe Software House
 
The Challenge of Bringing FEZ to PlayStation Platforms
The Challenge of Bringing FEZ to PlayStation PlatformsThe Challenge of Bringing FEZ to PlayStation Platforms
The Challenge of Bringing FEZ to PlayStation PlatformsMiguel Angel Horna
 
Fantom - Programming Language for JVM, CLR, and Javascript
Fantom - Programming Language for JVM, CLR, and JavascriptFantom - Programming Language for JVM, CLR, and Javascript
Fantom - Programming Language for JVM, CLR, and JavascriptKamil Toman
 
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан КольцовRust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан КольцовYandex
 
New Functional Features of Java 8
New Functional Features of Java 8New Functional Features of Java 8
New Functional Features of Java 8franciscoortin
 
please help finish sorting methods- import java-util-Arrays- import ja.pdf
please help finish sorting methods- import java-util-Arrays- import ja.pdfplease help finish sorting methods- import java-util-Arrays- import ja.pdf
please help finish sorting methods- import java-util-Arrays- import ja.pdfanfenterprises
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialjbellis
 

Similar to Add an interactive command line to your C++ application (20)

2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloading2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloading
 
Getting started cpp full
Getting started cpp   fullGetting started cpp   full
Getting started cpp full
 
Introduction to typescript
Introduction to typescriptIntroduction to typescript
Introduction to typescript
 
Hands on Session on Python
Hands on Session on PythonHands on Session on Python
Hands on Session on Python
 
Modern C++ Concurrency API
Modern C++ Concurrency APIModern C++ Concurrency API
Modern C++ Concurrency API
 
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbsSystem Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
 
Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++
 
Developer Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duoDeveloper Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duo
 
C++11
C++11C++11
C++11
 
Summary of C++17 features
Summary of C++17 featuresSummary of C++17 features
Summary of C++17 features
 
The Challenge of Bringing FEZ to PlayStation Platforms
The Challenge of Bringing FEZ to PlayStation PlatformsThe Challenge of Bringing FEZ to PlayStation Platforms
The Challenge of Bringing FEZ to PlayStation Platforms
 
TechTalk - Dotnet
TechTalk - DotnetTechTalk - Dotnet
TechTalk - Dotnet
 
CP 04.pptx
CP 04.pptxCP 04.pptx
CP 04.pptx
 
Fantom - Programming Language for JVM, CLR, and Javascript
Fantom - Programming Language for JVM, CLR, and JavascriptFantom - Programming Language for JVM, CLR, and Javascript
Fantom - Programming Language for JVM, CLR, and Javascript
 
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан КольцовRust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
 
New Functional Features of Java 8
New Functional Features of Java 8New Functional Features of Java 8
New Functional Features of Java 8
 
Function
FunctionFunction
Function
 
Oop object oriented programing topics
Oop object oriented programing topicsOop object oriented programing topics
Oop object oriented programing topics
 
please help finish sorting methods- import java-util-Arrays- import ja.pdf
please help finish sorting methods- import java-util-Arrays- import ja.pdfplease help finish sorting methods- import java-util-Arrays- import ja.pdf
please help finish sorting methods- import java-util-Arrays- import ja.pdf
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorial
 

Recently uploaded

Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
software engineering Chapter 5 System modeling.pptx
software engineering Chapter 5 System modeling.pptxsoftware engineering Chapter 5 System modeling.pptx
software engineering Chapter 5 System modeling.pptxnada99848
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 

Recently uploaded (20)

Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
software engineering Chapter 5 System modeling.pptx
software engineering Chapter 5 System modeling.pptxsoftware engineering Chapter 5 System modeling.pptx
software engineering Chapter 5 System modeling.pptx
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 

Add an interactive command line to your C++ application

  • 1. Add an interactive command line to your applications Daniele Pallastrelli, daniele77.github.io 13.01.2022, Italian C++
  • 2. My typical projects • Run for a long period of time • No classic interaction with the user (i.e., no GUI) • Run in a server, custom board, almost never desktop applications • They're not CPU bound applications
  • 3. Why an interactive console in your apps? • Need to have some sort of console to interact with my applications (e.g., embedded systems running around the clock) to: • monitor, • configure, • manage the system • E.g., CISCO routers • Traditional systems: SSH connections + logs
  • 4. Why an interactive console in your apps? • Debugging • Poke around internal state • Dump internal structures • Change the log level at runtime • Change the working mode • Enable / disable modules • Load / unload plugins • Early stage of development
  • 5. Reinventing the wheel? Existing solutions in open source domain: • Linux only • They're applications where you hook external programs to commands • No remote sessions • Few in C++ • None of them in "modern" C++
  • 6. Enter the shell (cli?) • My own library in C++14 • Production code quality • Used in several industrial projects • Demo time  • C++14 • Cross-platform (Linux and windows tested) • Menus and submenus • Command history (navigation with arrow keys) • Autocompletion (with TAB key) • Async interface • Colors
  • 7. Something missing… • Good when you start the app from a console (e.g. desktop applications or development stage) • What about processes that run in background (e.g., embedded, servers & c)?
  • 11.
  • 12. Features summary • C++14 • Header only • Cross-platform (linux and windows) • Menus and submenus • Remote sessions (telnet) • Persistent history (navigation with arrow keys) • Autocompletion (with TAB key) • Async interface • Colors
  • 13. auto rootMenu = make_unique<Menu>("cli"); rootMenu->Insert( "hello", [](std::ostream& out){ out << "Hello, worldn"; }, "Print hello world" ); rootMenu->Insert( "hello_everysession", [](std::ostream&){ Cli::cout() << "Hello, everybody" << std::endl; }, "Print hello everybody on all open sessions" ); rootMenu->Insert( "reverse", {"string_to_revert"}, [](std::ostream& out, const string& arg) { string copy(arg); std::reverse(copy.begin(), copy.end()); out << copy << "n"; }, "Print the reverse string" );
  • 14. rootMenu->Insert( "add", {"first_term", "second_term"}, [](std::ostream& out, int x, int y) { out << x << " + " << y << " = " << (x+y) << "n"; }, "Print the sum of the two numbers" ); rootMenu->Insert( "sort", {"list of strings separated by space"}, [](std::ostream& out, std::vector<std::string> data) { std::sort(data.begin(), data.end()); out << "sorted list: "; std::copy(data.begin(), data.end(), std::ostream_iterator<std::string>(out, " ")); out << "n"; }, "Alphabetically sort a list of words" );
  • 15. auto subMenu = make_unique<Menu>("sub"); subMenu->Insert( "demo", [](std::ostream& out){ out << "This is a sample!n"; }, "Print a demo string" ); rootMenu->Insert( std::move(subMenu) );
  • 16. // create a cli with the given root menu and a persistent storage Cli cli( std::move(rootMenu), std::make_unique<FileHistoryStorage>(".cli") ); // global exit action cli.ExitAction( [](auto& out){ out << "Goodbye and thanks for all the fish.n"; } ); // std exception custom handler cli.StdExceptionHandler( [](std::ostream& out, const std::string& cmd, const std::exception& e) { out << "Exception caught in cli handler: " << e.what() << " handling command: " << cmd << ".n"; } );
  • 17. LoopScheduler scheduler; CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200); localSession.ExitAction( [&scheduler](auto& out) // session exit action { out << "Closing App...n"; scheduler.Stop(); } ); scheduler.Run();
  • 18. StandaloneAsioScheduler scheduler; CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200); localSession.ExitAction( [&scheduler](auto& out) // session exit action { out << "Closing App...n"; scheduler.Stop(); } ); // setup server StandaloneAsioCliTelnetServer server(cli, scheduler, 5000); // exit action for all the connections server.ExitAction( [](auto& out) { out << "Terminating this session...n"; } ); scheduler.Run();
  • 19. How does it work
  • 20. Core idea • Command list • The user enters a string: command and parameters • Iteration over the command list: • Command name • Parameter number and type • The handler is called with the typed parameters
  • 22. class Command {}; class Menu : public Command { private: Menu* parent{ nullptr }; std::vector<Command*> cmds; }; template <typename F, typename ... Args> class VariadicFunctionCommand : public Command {};
  • 23. Menu is-a Command, because when you start the CLI, every Menu shows as a command you can digit at the prompt (e.g., if you define a Menu "foo", you get the command "foo" in the Cli to enter the submenu).
  • 24. auto rootMenu = make_unique<Menu>("cli"); rootMenu->Insert( "hello", [](std::ostream& out) { out << "Hello, worldn"; } ); rootMenu->Insert( "hello_everysession", [](std::ostream&) { Cli::cout() << "Hello, everybodyn"; } );
  • 25. auto subMenu = make_unique<Menu>("sub"); subMenu->Insert( "hello", [](std::ostream& out) { out << "Hello, submenu worldn"; } ); subMenu->Insert( "demo", [](std::ostream&) { out << "Demon"; } ); rootMenu->Insert( std::move(subMenu) );
  • 26. auto rootMenu = make_unique<Menu>("cli"); ... Cli cli( std::move(rootMenu) );
  • 27. auto rootMenu = make_unique<Menu>("cli"); ... Cli cli( std::move(rootMenu) ); CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200); CliTelnetServer server(cli, scheduler, 5000);
  • 28. Cli cli( std::move(rootMenu) ); CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200); CliTelnetServer server(cli, scheduler, 5000); CliFileSession fileSession(cli, infile, outfile); CliLocalTerminalSession localSession( scheduler, std::cout, 200); CliTelnetServer server(scheduler, 5000); CliFileSession fileSession(infile, outfile); Cli cli( std::move(rootMenu) ); cli.SetLocalSession( localSession ); cli.SetFileSession( fileSession ); cli.SetTelnetServer( server );
  • 29.
  • 30. rootMenu->Insert( "add", {"first_term", "second_term"}, [](std::ostream& out, int x, int y) { out << x << " + " << y << " = " << (x+y) << "n"; }, "Print the sum of two numbers" );
  • 31. rootMenu->Insert( "add", {"first_term", "second_term"}, [](std::ostream& out, int x, int y) { out << x << " + " << y << " = " << (x+y) << "n"; }, "Print the sum of two numbers" );
  • 32. Interlude – How do you get the type of a lambda argument? template <typename F> void foo(F f) { // what's the type of "f" first parameter? // something like: // using T = F::first_parameter_type ) foo( [](int){} );
  • 33. Interlude – How do you get the type of a lambda argument? template<typename F, typename Ret, typename A, typename... Rest> A helper(Ret (F::*)(A, Rest...) const); template <typename F> void foo(F f) { using T = decltype( helper(&F::operator()) ); } foo( [](int){} );
  • 34. class Menu : public Command { public: template <typename F> CmdHandler Insert(const string& cmdName, F f) { return CreateCmd(cmdName, f, &F::operator()); } private: template <typename F, typename R, typename ... Args> CmdHandler CreateCmd(const string& cmdName, F& f, R (F::*)(Args...) const) { auto cmd = make_unique< VariadicFunctionCommand< F, Args ... > >(cmdName, f); // insert cmd into this menu commands ... } }; Works with lambdas and std::function
  • 35. class Menu : public Command { public: ... template <typename R, typename ... Args> CmdHandler Insert(const std::string& cmdName, R (*f)(Args...)) { using F = R (*)(Args...); auto cmd = make_unique<VariadicFunctionCommand<F, Args ...>>(cmdName, f); // insert cmd into this menu commands ... } ... }; Overload for free- functions
  • 36. template <typename F, typename ... Args> class VariadicFunctionCommand : public Command { public: VariadicFunctionCommand(const std::string& _name, F fun) : Command(_name), func(std::move(fun)) {} bool Exec(const vector<string>& cmdLine) override { ... try { Select<Args...>::Exec(func, std::next(cmdLine.begin()), cmdLine.end()); } catch (std::bad_cast&) { return false; } return true; ... } };
  • 37. template <typename ... Args> struct Select; template <typename P, typename ... Args> struct Select<P, Args...> { template <typename F, typename InputIt> static void Exec(const F& f, InputIt first, InputIt last) { assert( first != last ); assert( std::distance(first, last) == 1+sizeof...(Args) ); const P firstPar = detail::from_string<typename std::decay<P>::type>(*first); auto g = [&](auto ... pars){ f(firstPar, pars...); }; Select<Args...>::Exec(g, std::next(first), last); } }; template <> struct Select<> { template <typename F, typename InputIt> static void Exec(const F& f, InputIt first, InputIt last) { assert(first == last); f(); } };
  • 38. Interlude How do you manage concurrency?
  • 39. Concurrency in my projects • Single thread (when possible), using Proactor pattern. • When I must: multiple threads, using Proactor pattern 
  • 40. By the way… …what's the PROACTOR pattern?
  • 41. The proactor pattern: Concurrency Without Threads
  • 42. The Proactor solution Split every application service into: • Long-duration operations. execute asynchronously • Completion handlers. processes the results of the associated asynchronous operations (potentially invoking additional asynchronous operations).
  • 43.
  • 44.
  • 47.
  • 48. Concurrency in my projects • asio for asynchonous I/O (timers, too) • asio::io_context available • When I/O is ready, asio puts handler in the asio::io_context • If more threads are needed (e.g., time consuming computations or blocking I/O), the result is put in asio::io_context • => everything runs in (my) single thread of execution
  • 49. Back to the library  • Input coming from: • Keyboard, using blocking primitives (std::getchar() and _getch()) • Sockets • Commands callbacks (in which thread?) • => proactor (asio::io_context)
  • 50. Consequences • The user must instantiate a boost::asio::io_context object • The whole library depends on boost::asio
  • 51. Concurrency summary (v. 1.0) • The library depends on boost::asio, even when you don't need the telnet server • Library users ask to use standalone asio instead of boost::asio • The truth is that the whole library depends on boost::asio because: • Telnet server needs it • Keyboard handler needs an event handler • The two must use the same event manager, i.e. boost::asio::io_context
  • 52. Release 2.0 – Goals: • Optionally use standalone asio instead of boost::asio for the telnet server • Remove all dependencies if the telnet server is not needed
  • 53. Release 2.0 – The solution • New abstraction: "Scheduler" • schedules async event • The library provides three kind of schedulers: • StandaloneAsioScheduler (based on asio::io_context) • BoostAsioScheduler (based on boost::asio::io_context) • LoopScheduler (hand made sync queue)
  • 54. Release 2.0 – The solution • Cli library can use all the schedulers, but if you need the telnet server you must use *AsioScheduler • Bottom line: • If ( you need telnet server OR your app already uses [boost::]asio::io_context => StandaloneAsioScheduler or BoostAsioScheduler • Else => LoopScheduler (no external dependencies)
  • 55. Release 2.0 – Standalone Asio #include <cli/standaloneasioscheduler.h> #include <cli/standaloneasioremotecli.h> ... StandaloneAsioScheduler scheduler; // setup local session CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200); // setup server StandaloneAsioCliTelnetServer server(cli, scheduler, 5000); // start event loop scheduler.Run();
  • 56. Release 2.0 – Boost Asio #include <cli/boostasioscheduler.h> #include <cli/boostasioremotecli.h> ... BoostAsioScheduler scheduler; // setup local session CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200); // setup server BoostAsioCliTelnetServer server(cli, scheduler, 5000); // start event loop scheduler.Run();
  • 57. Release 2.0 – No Asio #include <cli/loopscheduler.h> ... LoopScheduler scheduler; // setup local session CliLocalTerminalSession localSession(cli, scheduler, std::cout, 200); // start event loop scheduler.Run();
  • 59. Miles to go… • User-defined arguments (and completion for them) • More (bash-like) shortcuts • Conan support • Rename the library (?)
  • 60. Library core: design decisions • Reflection (?) • Preprocessors (???) • "Composite" Design Pattern VS Template metaprogramming
  • 61. Intentional architecture VS emergent design "Many times, thinking things out in advance saved us serious development headaches later on. ... [on making a particular specification change] ... Making this change in the spec took an hour or two. If we had made this change in code, it would have added weeks to the schedule. I can’t tell you how strongly I believe in Big Design Up Front, which the proponents of Extreme Programming consider anathema. I have consistently saved time and made better products by using BDUF and I’m proud to use it, no matter what the XP fanatics claim. They’re just wrong on this point and I can’t be any clearer than that." -- Joel Spolsky "The project Aardwark Spec" – Joel On Software
  • 62. Take away • Use the right technique • Use Cli library  (when you need it) • Use Proactor pattern (when you need it) • Use your brain (always)
  • 63. References Me: daniele.pallastrelli@gmail.com Me: @DPallastrelli Github: http://github.com/daniele77 Web: daniele77.github.io 63